Skip to content

Commit d3263c1

Browse files
authored
fix(executor): handle fragments while resolving the introspection (#411)
Fixes #409
1 parent cd3a3fc commit d3263c1

File tree

1 file changed

+157
-35
lines changed

1 file changed

+157
-35
lines changed

lib/executor/src/introspection/resolve.rs

Lines changed: 157 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,18 @@ fn resolve_input_value<'exec, 'schema: 'exec>(
6969
selections: &'exec SelectionSet,
7070
ctx: &'exec IntrospectionContext<'exec, 'schema>,
7171
) -> Value<'exec> {
72-
let mut iv_data = Vec::with_capacity(selections.items.len());
73-
for item in &selections.items {
72+
let mut iv_data = resolve_input_value_selections(iv, &selections.items, ctx);
73+
iv_data.sort_by_key(|(k, _)| *k);
74+
Value::Object(iv_data)
75+
}
76+
77+
fn resolve_input_value_selections<'exec, 'schema: 'exec>(
78+
iv: &'exec InputValue<'schema, String>,
79+
selection_items: &'exec Vec<SelectionItem>,
80+
ctx: &'exec IntrospectionContext<'exec, 'schema>,
81+
) -> Vec<(&'exec str, Value<'exec>)> {
82+
let mut iv_data: Vec<(&str, Value<'_>)> = Vec::with_capacity(selection_items.len());
83+
for item in selection_items {
7484
if let SelectionItem::Field(field) = item {
7585
let value = match field.name.as_str() {
7686
"name" => Value::String(&iv.name),
@@ -84,20 +94,34 @@ fn resolve_input_value<'exec, 'schema: 'exec>(
8494
_ => Value::Null,
8595
};
8696
iv_data.push((field.selection_identifier(), value));
97+
} else if let SelectionItem::InlineFragment(_) = item {
98+
let selection_items = item.selections();
99+
if let Some(selection_items) = selection_items {
100+
let new_data = resolve_input_value_selections(iv, selection_items, ctx);
101+
iv_data.extend(new_data);
102+
}
87103
}
88104
}
89-
iv_data.sort_by_key(|(k, _)| *k);
90-
Value::Object(iv_data)
105+
iv_data
91106
}
92107

93108
fn resolve_field<'exec, 'schema: 'exec>(
94109
f: &'exec Field<'schema, String>,
95110
selections: &'exec SelectionSet,
96111
ctx: &'exec IntrospectionContext<'exec, 'schema>,
97112
) -> Value<'exec> {
98-
let mut field_data = Vec::with_capacity(selections.items.len());
113+
let mut field_data = resolve_field_selections(f, &selections.items, ctx);
114+
field_data.sort_by_key(|(k, _)| *k);
115+
Value::Object(field_data)
116+
}
99117

100-
for item in &selections.items {
118+
fn resolve_field_selections<'exec, 'schema: 'exec>(
119+
f: &'exec Field<'schema, String>,
120+
selection_items: &'exec Vec<SelectionItem>,
121+
ctx: &'exec IntrospectionContext<'exec, 'schema>,
122+
) -> Vec<(&'exec str, Value<'exec>)> {
123+
let mut field_data = Vec::with_capacity(selection_items.len());
124+
for item in selection_items {
101125
if let SelectionItem::Field(field) = item {
102126
let value = match field.name.as_str() {
103127
"name" => Value::String(&f.name),
@@ -122,19 +146,32 @@ fn resolve_field<'exec, 'schema: 'exec>(
122146
_ => Value::Null,
123147
};
124148
field_data.push((field.selection_identifier(), value));
149+
} else if let SelectionItem::InlineFragment(_) = item {
150+
let selection_items = item.selections();
151+
if let Some(selection_items) = selection_items {
152+
let new_data = resolve_field_selections(f, selection_items, ctx);
153+
field_data.extend(new_data);
154+
}
125155
}
126156
}
127-
field_data.sort_by_key(|(k, _)| *k);
128-
Value::Object(field_data)
157+
field_data
129158
}
130159

131160
fn resolve_enum_value<'exec, 'schema: 'exec>(
132161
ev: &'exec EnumValue<'schema, String>,
133162
selections: &'exec SelectionSet,
134163
) -> Value<'exec> {
135-
let mut ev_data = Vec::with_capacity(selections.items.len());
164+
let mut ev_data = resolve_enum_value_selections(ev, &selections.items);
165+
ev_data.sort_by_key(|(k, _)| *k);
166+
Value::Object(ev_data)
167+
}
136168

137-
for item in &selections.items {
169+
fn resolve_enum_value_selections<'exec, 'schema: 'exec>(
170+
ev: &'exec EnumValue<'schema, String>,
171+
selection_items: &'exec Vec<SelectionItem>,
172+
) -> Vec<(&'exec str, Value<'exec>)> {
173+
let mut ev_data = Vec::with_capacity(selection_items.len());
174+
for item in selection_items {
138175
if let SelectionItem::Field(field) = item {
139176
let value = match field.name.as_str() {
140177
"name" => Value::String(&ev.name),
@@ -150,20 +187,35 @@ fn resolve_enum_value<'exec, 'schema: 'exec>(
150187
_ => Value::Null,
151188
};
152189
ev_data.push((field.selection_identifier(), value));
190+
} else if let SelectionItem::InlineFragment(_) = item {
191+
let selection_items = item.selections();
192+
if let Some(selection_items) = selection_items {
193+
let new_data = resolve_enum_value_selections(ev, selection_items);
194+
ev_data.extend(new_data);
195+
}
153196
}
154197
}
155-
ev_data.sort_by_key(|(k, _)| *k);
156-
Value::Object(ev_data)
198+
ev_data
157199
}
158200

159201
fn resolve_type_definition<'exec, 'schema: 'exec>(
160202
type_def: &'exec TypeDefinition<'schema, String>,
161203
selections: &'exec SelectionSet,
162204
ctx: &'exec IntrospectionContext<'exec, 'schema>,
163205
) -> Value<'exec> {
164-
let mut type_data = Vec::with_capacity(selections.items.len());
206+
let mut type_data = resolve_type_definition_selections(type_def, &selections.items, ctx);
207+
type_data.sort_by_key(|(k, _)| *k);
208+
Value::Object(type_data)
209+
}
165210

166-
for item in &selections.items {
211+
fn resolve_type_definition_selections<'exec, 'schema: 'exec>(
212+
type_def: &'exec TypeDefinition<'schema, String>,
213+
selection_items: &'exec Vec<SelectionItem>,
214+
ctx: &'exec IntrospectionContext<'exec, 'schema>,
215+
) -> Vec<(&'exec str, Value<'exec>)> {
216+
let mut type_data = Vec::with_capacity(selection_items.len());
217+
218+
for item in selection_items {
167219
if let SelectionItem::Field(field) = item {
168220
let value = match field.name.as_str() {
169221
"kind" => Value::String(kind_to_str(type_def)),
@@ -208,7 +260,10 @@ fn resolve_type_definition<'exec, 'schema: 'exec>(
208260

209261
let fields_values: Vec<Value<'exec>> = fields
210262
.iter()
211-
.filter(|f| include_deprecated || !is_deprecated(&f.directives))
263+
.filter(|f| {
264+
!f.name.starts_with("__")
265+
&& (include_deprecated || !is_deprecated(&f.directives))
266+
})
212267
.map(|f| resolve_field(f, &field.selections, ctx))
213268
.collect();
214269
Value::Array(fields_values)
@@ -286,21 +341,35 @@ fn resolve_type_definition<'exec, 'schema: 'exec>(
286341
_ => Value::Null,
287342
};
288343
type_data.push((field.selection_identifier(), value));
344+
} else if let SelectionItem::InlineFragment(_) = item {
345+
let selection_items = item.selections();
346+
if let Some(selection_items) = selection_items {
347+
let new_data = resolve_type_definition_selections(type_def, selection_items, ctx);
348+
type_data.extend(new_data);
349+
}
289350
}
290351
}
291-
292-
type_data.sort_by_key(|(k, _)| *k);
293-
Value::Object(type_data)
352+
type_data
294353
}
295-
296354
fn resolve_wrapper_type<'exec, 'schema: 'exec>(
297355
kind: &'exec str,
298356
inner_type: &'exec Type<'schema, String>,
299357
selections: &'exec SelectionSet,
300358
ctx: &'exec IntrospectionContext<'exec, 'schema>,
301359
) -> Value<'exec> {
302-
let mut type_data = Vec::with_capacity(selections.items.len());
303-
for item in &selections.items {
360+
let mut type_data = resolve_wrapper_type_selections(kind, inner_type, &selections.items, ctx);
361+
type_data.sort_by_key(|(k, _)| *k);
362+
Value::Object(type_data)
363+
}
364+
365+
fn resolve_wrapper_type_selections<'exec, 'schema: 'exec>(
366+
kind: &'exec str,
367+
inner_type: &'exec Type<'schema, String>,
368+
selection_items: &'exec Vec<SelectionItem>,
369+
ctx: &'exec IntrospectionContext<'exec, 'schema>,
370+
) -> Vec<(&'exec str, Value<'exec>)> {
371+
let mut type_data = Vec::with_capacity(selection_items.len());
372+
for item in selection_items {
304373
if let SelectionItem::Field(field) = item {
305374
let value = match field.name.as_str() {
306375
"kind" => Value::String(kind),
@@ -310,10 +379,16 @@ fn resolve_wrapper_type<'exec, 'schema: 'exec>(
310379
_ => Value::Null,
311380
};
312381
type_data.push((field.selection_identifier(), value));
382+
} else if let SelectionItem::InlineFragment(_) = item {
383+
let selection_items = item.selections();
384+
if let Some(selection_items) = selection_items {
385+
let new_data =
386+
resolve_wrapper_type_selections(kind, inner_type, selection_items, ctx);
387+
type_data.extend(new_data);
388+
}
313389
}
314390
}
315-
type_data.sort_by_key(|(k, _)| *k);
316-
Value::Object(type_data)
391+
type_data
317392
}
318393

319394
fn resolve_type<'exec, 'schema: 'exec>(
@@ -336,8 +411,18 @@ fn resolve_directive<'exec, 'schema: 'exec>(
336411
selections: &'exec SelectionSet,
337412
ctx: &'exec IntrospectionContext<'exec, 'schema>,
338413
) -> Value<'exec> {
339-
let mut directive_data = Vec::with_capacity(selections.items.len());
340-
for item in &selections.items {
414+
let mut directive_data = resolve_directive_selections(d, &selections.items, ctx);
415+
directive_data.sort_by_key(|(k, _)| *k);
416+
Value::Object(directive_data)
417+
}
418+
419+
fn resolve_directive_selections<'exec, 'schema: 'exec>(
420+
d: &'exec DirectiveDefinition<'schema, String>,
421+
selection_items: &'exec Vec<SelectionItem>,
422+
ctx: &'exec IntrospectionContext<'exec, 'schema>,
423+
) -> Vec<(&'exec str, Value<'exec>)> {
424+
let mut directive_data = Vec::with_capacity(selection_items.len());
425+
for item in selection_items {
341426
if let SelectionItem::Field(field) = item {
342427
let value = match field.name.as_str() {
343428
"name" => Value::String(&d.name),
@@ -366,19 +451,34 @@ fn resolve_directive<'exec, 'schema: 'exec>(
366451
_ => Value::Null,
367452
};
368453
directive_data.push((field.selection_identifier(), value));
454+
} else if let SelectionItem::InlineFragment(_) = item {
455+
let selection_items = item.selections();
456+
if let Some(selection_items) = selection_items {
457+
let new_data = resolve_directive_selections(d, selection_items, ctx);
458+
directive_data.extend(new_data);
459+
}
369460
}
370461
}
371-
directive_data.sort_by_key(|(k, _)| *k);
372-
Value::Object(directive_data)
462+
directive_data
373463
}
374464

375465
fn resolve_schema_field<'exec, 'schema: 'exec>(
376466
field: &'exec FieldSelection,
377467
ctx: &'exec IntrospectionContext<'exec, 'schema>,
378468
) -> Value<'exec> {
379-
let mut schema_data = Vec::with_capacity(field.selections.items.len());
469+
let mut schema_data = resolve_schema_selections(&field.selections.items, ctx);
470+
471+
schema_data.sort_by_key(|(k, _)| *k);
472+
Value::Object(schema_data)
473+
}
380474

381-
for item in &field.selections.items {
475+
fn resolve_schema_selections<'exec, 'schema: 'exec>(
476+
items: &'exec Vec<SelectionItem>,
477+
ctx: &'exec IntrospectionContext<'exec, 'schema>,
478+
) -> Vec<(&'exec str, Value<'exec>)> {
479+
let mut schema_data = Vec::with_capacity(items.len());
480+
481+
for item in items {
382482
if let SelectionItem::Field(inner_field) = item {
383483
let value = match inner_field.name.as_str() {
384484
"description" => Value::Null,
@@ -429,10 +529,15 @@ fn resolve_schema_field<'exec, 'schema: 'exec>(
429529
_ => Value::Null,
430530
};
431531
schema_data.push((inner_field.selection_identifier(), value));
532+
} else if let SelectionItem::FragmentSpread(_) = item {
533+
let selection_items = item.selections();
534+
if let Some(selection_items) = selection_items {
535+
let new_data = resolve_schema_selections(selection_items, ctx);
536+
schema_data.extend(new_data);
537+
}
432538
}
433539
}
434-
schema_data.sort_by_key(|(k, _)| *k);
435-
Value::Object(schema_data)
540+
schema_data
436541
}
437542

438543
pub fn resolve_introspection<'exec, 'schema: 'exec>(
@@ -454,9 +559,20 @@ pub fn resolve_introspection<'exec, 'schema: 'exec>(
454559
})
455560
.unwrap_or_else(|| ctx.schema.query_type_name());
456561

457-
let mut data = Vec::with_capacity(root_selection_set.items.len());
562+
let mut data =
563+
resolve_root_introspection_selections(root_type_name, &root_selection_set.items, ctx);
564+
565+
data.sort_by_key(|(k, _)| *k);
566+
Value::Object(data)
567+
}
458568

459-
for item in &root_selection_set.items {
569+
fn resolve_root_introspection_selections<'exec, 'schema: 'exec>(
570+
root_type_name: &'schema str,
571+
items: &'exec Vec<SelectionItem>,
572+
ctx: &'exec IntrospectionContext,
573+
) -> Vec<(&'exec str, Value<'exec>)> {
574+
let mut data = Vec::with_capacity(items.len());
575+
for item in items {
460576
if let SelectionItem::Field(field) = item {
461577
let value = match field.name.as_str() {
462578
"__schema" => resolve_schema_field(field, ctx),
@@ -477,10 +593,16 @@ pub fn resolve_introspection<'exec, 'schema: 'exec>(
477593
_ => Value::Null,
478594
};
479595
data.push((field.selection_identifier(), value));
596+
} else if let SelectionItem::InlineFragment(_) = item {
597+
let selection_items = item.selections();
598+
if let Some(selection_items) = selection_items {
599+
let new_data =
600+
resolve_root_introspection_selections(root_type_name, selection_items, ctx);
601+
data.extend(new_data);
602+
}
480603
}
481604
}
482-
data.sort_by_key(|(k, _)| *k);
483-
Value::Object(data)
605+
data
484606
}
485607

486608
trait TypeDefinitionExtension {

0 commit comments

Comments
 (0)