1use crate::ast::definition::{
2 directive_definition::BuiltinDirectiveDefinition, BaseInputType, BaseOutputType, Context,
3 CustomScalarTypeDefinition, DefaultContext, DirectiveDefinition, Directives,
4 EnumTypeDefinition, ExplicitSchemaDefinition, FieldsDefinition, InputObjectTypeDefinition,
5 InputValueDefinition, InterfaceImplementations, InterfaceTypeDefinition, ObjectTypeDefinition,
6 SchemaDefinition, TypeDefinition, UnionTypeDefinition,
7};
8use crate::ast::{DepthLimiter, FromTokens, Parse, ParseError, Tokens};
9use crate::Error;
10use bluejay_core::definition::{prelude::*, HasDirectives};
11use bluejay_core::{
12 AsIter, BuiltinScalarDefinition, Directive as _, IntoEnumIterator, OperationType,
13};
14use std::collections::btree_map::Entry;
15use std::collections::{BTreeMap, HashMap, HashSet};
16
17mod definition_document_error;
18use definition_document_error::DefinitionDocumentError;
19
20#[derive(Debug)]
21pub struct DefinitionDocument<'a, C: Context = DefaultContext> {
22 schema_definitions: Vec<ExplicitSchemaDefinition<'a, C>>,
23 directive_definitions: Vec<DirectiveDefinition<'a, C>>,
24 type_definitions: Vec<TypeDefinition<'a, C>>,
25}
26
27#[derive(Debug)]
28pub struct ImplicitSchemaDefinition<'a, C: Context> {
29 query: &'a ObjectTypeDefinition<'a, C>,
30 mutation: Option<&'a ObjectTypeDefinition<'a, C>>,
31 subscription: Option<&'a ObjectTypeDefinition<'a, C>>,
32}
33
34type ExplicitSchemaDefinitionWithRootTypes<'a, C> = (
35 &'a ExplicitSchemaDefinition<'a, C>,
36 &'a ObjectTypeDefinition<'a, C>,
37 Option<&'a ObjectTypeDefinition<'a, C>>,
38 Option<&'a ObjectTypeDefinition<'a, C>>,
39);
40
41impl<'a, C: Context> Parse<'a> for DefinitionDocument<'a, C> {
42 fn parse_from_tokens(
43 mut tokens: impl Tokens<'a>,
44 max_depth: usize,
45 ) -> Result<Self, Vec<Error>> {
46 let mut instance: Self = Self::new();
47 let mut errors = Vec::new();
48 let mut last_pass_had_error = false;
49
50 loop {
51 match Self::next_definition_identifier(&mut tokens) {
52 Some(CustomScalarTypeDefinition::<C>::SCALAR_IDENTIFIER) => {
53 Self::parse_definition::<_, CustomScalarTypeDefinition<C>>(
54 &mut instance.type_definitions,
55 &mut tokens,
56 &mut errors,
57 &mut last_pass_had_error,
58 max_depth,
59 )
60 }
61 Some(ObjectTypeDefinition::<C>::TYPE_IDENTIFIER) => {
62 Self::parse_definition::<_, ObjectTypeDefinition<C>>(
63 &mut instance.type_definitions,
64 &mut tokens,
65 &mut errors,
66 &mut last_pass_had_error,
67 max_depth,
68 )
69 }
70 Some(InputObjectTypeDefinition::<C>::INPUT_IDENTIFIER) => {
71 Self::parse_definition::<_, InputObjectTypeDefinition<C>>(
72 &mut instance.type_definitions,
73 &mut tokens,
74 &mut errors,
75 &mut last_pass_had_error,
76 max_depth,
77 )
78 }
79 Some(EnumTypeDefinition::<C>::ENUM_IDENTIFIER) => {
80 Self::parse_definition::<_, EnumTypeDefinition<C>>(
81 &mut instance.type_definitions,
82 &mut tokens,
83 &mut errors,
84 &mut last_pass_had_error,
85 max_depth,
86 )
87 }
88 Some(UnionTypeDefinition::<C>::UNION_IDENTIFIER) => {
89 Self::parse_definition::<_, UnionTypeDefinition<C>>(
90 &mut instance.type_definitions,
91 &mut tokens,
92 &mut errors,
93 &mut last_pass_had_error,
94 max_depth,
95 )
96 }
97 Some(InterfaceTypeDefinition::<C>::INTERFACE_IDENTIFIER) => {
98 Self::parse_definition::<_, InterfaceTypeDefinition<C>>(
99 &mut instance.type_definitions,
100 &mut tokens,
101 &mut errors,
102 &mut last_pass_had_error,
103 max_depth,
104 )
105 }
106 Some(ExplicitSchemaDefinition::<C>::SCHEMA_IDENTIFIER) => {
107 Self::parse_definition::<_, ExplicitSchemaDefinition<C>>(
108 &mut instance.schema_definitions,
109 &mut tokens,
110 &mut errors,
111 &mut last_pass_had_error,
112 max_depth,
113 )
114 }
115 Some(DirectiveDefinition::<C>::DIRECTIVE_IDENTIFIER) => {
116 Self::parse_definition::<_, DirectiveDefinition<C>>(
117 &mut instance.directive_definitions,
118 &mut tokens,
119 &mut errors,
120 &mut last_pass_had_error,
121 max_depth,
122 )
123 }
124 _ => {
125 if let Some(token) = tokens.next() {
126 if !last_pass_had_error {
127 errors.push(ParseError::UnexpectedToken { span: token.into() });
128 last_pass_had_error = true;
129 }
130 } else {
131 break;
132 }
133 }
134 }
135 }
136
137 let lex_errors = tokens.into_errors();
138
139 let errors = if lex_errors.is_empty() {
140 if errors.is_empty() && instance.is_empty() {
141 vec![ParseError::EmptyDocument.into()]
142 } else {
143 errors.into_iter().map(Into::into).collect()
144 }
145 } else {
146 lex_errors.into_iter().map(Into::into).collect()
147 };
148
149 if errors.is_empty() {
150 instance.insert_builtin_scalar_definitions();
151 instance.insert_builtin_directive_definitions();
152 instance.add_query_root_fields();
153 Ok(instance)
154 } else {
155 Err(errors)
156 }
157 }
158}
159
160impl<'a, C: Context> DefinitionDocument<'a, C> {
161 fn new() -> Self {
162 Self {
163 schema_definitions: Vec::new(),
164 directive_definitions: Vec::new(),
165 type_definitions: vec![
166 ObjectTypeDefinition::__schema().into(),
167 ObjectTypeDefinition::__type().into(),
168 ObjectTypeDefinition::__field().into(),
169 ObjectTypeDefinition::__input_value().into(),
170 ObjectTypeDefinition::__enum_value().into(),
171 ObjectTypeDefinition::__directive().into(),
172 EnumTypeDefinition::__type_kind().into(),
173 EnumTypeDefinition::__directive_location().into(),
174 ],
175 }
176 }
177
178 fn parse_definition<'b, S, T: FromTokens<'b> + Into<S>>(
179 definitions: &mut Vec<S>,
180 tokens: &mut impl Tokens<'b>,
181 errors: &mut Vec<ParseError>,
182 last_pass_had_error: &mut bool,
183 max_depth: usize,
184 ) {
185 match T::from_tokens(tokens, DepthLimiter::new(max_depth)) {
186 Ok(definition) => {
187 definitions.push(definition.into());
188 *last_pass_had_error = false;
189 }
190 Err(err) => {
191 if !*last_pass_had_error {
192 errors.push(err);
193 *last_pass_had_error = true;
194 }
195 }
196 }
197 }
198
199 fn insert_builtin_scalar_definitions(&mut self) {
202 let mut builtin_scalars_by_name: HashMap<&str, BuiltinScalarDefinition> =
203 HashMap::from_iter(BuiltinScalarDefinition::iter().map(|bstd| (bstd.name(), bstd)));
204
205 self.type_definitions.iter().for_each(|td| {
206 builtin_scalars_by_name.remove(td.name());
207 });
208
209 self.type_definitions.extend(
210 builtin_scalars_by_name
211 .into_values()
212 .map(TypeDefinition::BuiltinScalar),
213 );
214 }
215
216 fn insert_builtin_directive_definitions(&mut self) {
219 let mut builtin_directive_definitions_by_name: HashMap<&str, BuiltinDirectiveDefinition> =
220 HashMap::from_iter(
221 BuiltinDirectiveDefinition::iter()
222 .map(|bdd: BuiltinDirectiveDefinition| (bdd.into(), bdd)),
223 );
224
225 self.directive_definitions().iter().for_each(|dd| {
226 builtin_directive_definitions_by_name.remove(dd.name());
227 });
228
229 self.directive_definitions.extend(
230 builtin_directive_definitions_by_name
231 .into_values()
232 .map(DirectiveDefinition::from),
233 );
234 }
235
236 fn add_query_root_fields(&mut self) {
237 let explicit_query_roots: HashSet<&str> = HashSet::from_iter(
238 self.schema_definitions
239 .iter()
240 .flat_map(|schema_definition| {
241 schema_definition
242 .root_operation_type_definitions()
243 .iter()
244 .filter(|rotd| rotd.operation_type() == OperationType::Query)
245 .map(|rotd| rotd.name())
246 }),
247 );
248
249 self.type_definitions
250 .iter_mut()
251 .for_each(|type_definition| {
252 if let TypeDefinition::Object(otd) = type_definition {
253 let name = otd.name().as_ref();
254 if name == "Query" || explicit_query_roots.contains(name) {
255 otd.add_query_root_fields();
256 }
257 }
258 })
259 }
260
261 fn is_empty(&self) -> bool {
262 self.definition_count() == 0
263 }
264
265 fn next_definition_identifier(tokens: &mut impl Tokens<'a>) -> Option<&str> {
266 let idx_to_peek = if tokens.peek_string_value(0) { 1 } else { 0 };
267 tokens.peek_name(idx_to_peek).map(AsRef::as_ref)
268 }
269
270 pub fn definition_count(&self) -> usize {
271 self.directive_definitions
272 .iter()
273 .filter(|dd| !dd.is_builtin())
274 .count()
275 + self.schema_definitions.len()
276 + self
277 .type_definitions
278 .iter()
279 .filter(|td| !td.as_ref().is_builtin())
280 .count()
281 }
282
283 pub fn directive_definitions(&self) -> &[DirectiveDefinition<'a, C>] {
284 &self.directive_definitions
285 }
286
287 fn index_directive_definitions(
288 &'a self,
289 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
290 ) -> BTreeMap<&'a str, &'a DirectiveDefinition<'a, C>> {
291 let mut indexed: BTreeMap<&str, &DirectiveDefinition<'a, C>> = BTreeMap::new();
292 let mut duplicates: BTreeMap<&str, Vec<&DirectiveDefinition<'a, C>>> = BTreeMap::new();
293
294 self.directive_definitions
295 .iter()
296 .for_each(|directive_definition| {
297 match indexed.entry(directive_definition.name().as_ref()) {
298 Entry::Vacant(entry) => {
299 entry.insert(directive_definition);
300 }
301 Entry::Occupied(entry) => {
302 duplicates
303 .entry(directive_definition.name().as_ref())
304 .or_insert_with(|| vec![entry.get()])
305 .push(directive_definition);
306 }
307 }
308 });
309
310 errors.extend(duplicates.into_iter().map(|(name, definitions)| {
311 DefinitionDocumentError::DuplicateDirectiveDefinitions { name, definitions }
312 }));
313
314 indexed
315 }
316
317 fn index_type_definitions(
318 &'a self,
319 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
320 ) -> BTreeMap<&'a str, &'a TypeDefinition<'a, C>> {
321 let mut indexed: BTreeMap<&str, &TypeDefinition<'a, C>> = BTreeMap::new();
322 let mut duplicates: BTreeMap<&str, Vec<&TypeDefinition<'a, C>>> = BTreeMap::new();
323
324 self.type_definitions
325 .iter()
326 .for_each(|td| match indexed.entry(td.name()) {
327 Entry::Vacant(entry) => {
328 entry.insert(td);
329 }
330 Entry::Occupied(entry) => {
331 duplicates
332 .entry(td.name())
333 .or_insert_with(|| vec![entry.get()])
334 .push(td);
335 }
336 });
337
338 errors.extend(duplicates.into_iter().map(|(name, definitions)| {
339 DefinitionDocumentError::DuplicateTypeDefinitions { name, definitions }
340 }));
341
342 indexed
343 }
344
345 fn implicit_schema_definition(
346 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
347 ) -> Result<Option<ImplicitSchemaDefinition<'a, C>>, Vec<DefinitionDocumentError<'a, C>>> {
348 let mut errors = Vec::new();
349 let query =
350 Self::implicit_root_operation_type("Query", indexed_type_definitions, &mut errors);
351 let mutation =
352 Self::implicit_root_operation_type("Mutation", indexed_type_definitions, &mut errors);
353 let subscription = Self::implicit_root_operation_type(
354 "Subscription",
355 indexed_type_definitions,
356 &mut errors,
357 );
358
359 if !errors.is_empty() {
360 return Err(errors);
361 }
362
363 if let Some(query) = query {
364 Ok(Some(ImplicitSchemaDefinition {
365 query,
366 mutation,
367 subscription,
368 }))
369 } else if mutation.is_some() || subscription.is_some() {
370 Err(vec![
371 DefinitionDocumentError::ImplicitSchemaDefinitionMissingQuery,
372 ])
373 } else {
374 Ok(None)
375 }
376 }
377
378 fn implicit_root_operation_type(
379 name: &str,
380 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
381 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
382 ) -> Option<&'a ObjectTypeDefinition<'a, C>> {
383 match indexed_type_definitions.get(name) {
384 Some(TypeDefinition::Object(o)) => Some(o),
385 Some(definition) => {
386 errors.push(
387 DefinitionDocumentError::ImplicitRootOperationTypeNotAnObject { definition },
388 );
389 None
390 }
391 None => None,
392 }
393 }
394
395 fn explicit_schema_definition(
396 &'a self,
397 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
398 ) -> Result<
399 Option<ExplicitSchemaDefinitionWithRootTypes<'a, C>>,
400 Vec<DefinitionDocumentError<'a, C>>,
401 > {
402 let mut errors = Vec::new();
403 if let Some(first) = self.schema_definitions.first() {
404 if self.schema_definitions.len() == 1 {
405 let query = match Self::explicit_operation_type_definition(
406 OperationType::Query,
407 first,
408 indexed_type_definitions,
409 ) {
410 Ok(query) => query,
411 Err(err) => {
412 errors.push(err);
413 None
414 }
415 };
416 let mutation = match Self::explicit_operation_type_definition(
417 OperationType::Mutation,
418 first,
419 indexed_type_definitions,
420 ) {
421 Ok(mutation) => mutation,
422 Err(err) => {
423 errors.push(err);
424 None
425 }
426 };
427 let subscription = match Self::explicit_operation_type_definition(
428 OperationType::Subscription,
429 first,
430 indexed_type_definitions,
431 ) {
432 Ok(subscription) => subscription,
433 Err(err) => {
434 errors.push(err);
435 None
436 }
437 };
438 if !errors.is_empty() {
439 return Err(errors);
440 }
441 if let Some(query) = query {
442 Ok(Some((first, query, mutation, subscription)))
443 } else {
444 Err(vec![
445 DefinitionDocumentError::ExplicitSchemaDefinitionMissingQuery {
446 definition: first,
447 },
448 ])
449 }
450 } else {
451 Err(vec![
452 DefinitionDocumentError::DuplicateExplicitSchemaDefinitions {
453 definitions: &self.schema_definitions,
454 },
455 ])
456 }
457 } else {
458 Ok(None)
459 }
460 }
461
462 fn explicit_operation_type_definition(
463 operation_type: OperationType,
464 explicit_schema_definition: &'a ExplicitSchemaDefinition<'a, C>,
465 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
466 ) -> Result<Option<&'a ObjectTypeDefinition<'a, C>>, DefinitionDocumentError<'a, C>> {
467 let root_operation_type_definitions: Vec<_> = explicit_schema_definition
468 .root_operation_type_definitions()
469 .iter()
470 .filter(|rotd| rotd.operation_type() == operation_type)
471 .collect();
472
473 if let Some(first) = root_operation_type_definitions.first() {
474 if root_operation_type_definitions.len() == 1 {
475 match indexed_type_definitions.get(first.name()) {
476 Some(TypeDefinition::Object(o)) => Ok(Some(o)),
477 Some(_) => Err(
478 DefinitionDocumentError::ExplicitRootOperationTypeNotAnObject {
479 name: first.name_token(),
480 },
481 ),
482 None => Err(
483 DefinitionDocumentError::ExplicitRootOperationTypeDoesNotExist {
484 root_operation_type_definition: first,
485 },
486 ),
487 }
488 } else {
489 Err(
490 DefinitionDocumentError::DuplicateExplicitRootOperationDefinitions {
491 operation_type,
492 root_operation_type_definitions,
493 },
494 )
495 }
496 } else {
497 Ok(None)
498 }
499 }
500
501 fn resolve_type_and_directive_definitions(
502 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
503 indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
504 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
505 ) {
506 indexed_type_definitions
507 .values()
508 .for_each(|type_definition| match type_definition {
509 TypeDefinition::Object(otd) => {
510 Self::resolve_fields_definition_types_and_directives(
511 indexed_type_definitions,
512 indexed_directive_definitions,
513 otd.fields_definition(),
514 errors,
515 );
516 if let Some(interface_implementations) = otd.interface_implementations() {
517 Self::resolve_interface_implementations(
518 indexed_type_definitions,
519 interface_implementations,
520 errors,
521 );
522 }
523 Self::resolve_directive_definitions(indexed_directive_definitions, otd, errors);
524 }
525 TypeDefinition::Interface(itd) => {
526 Self::resolve_fields_definition_types_and_directives(
527 indexed_type_definitions,
528 indexed_directive_definitions,
529 itd.fields_definition(),
530 errors,
531 );
532 if let Some(interface_implementations) = itd.interface_implementations() {
533 Self::resolve_interface_implementations(
534 indexed_type_definitions,
535 interface_implementations,
536 errors,
537 );
538 }
539 Self::resolve_directive_definitions(indexed_directive_definitions, itd, errors);
540 }
541 TypeDefinition::Union(utd) => {
542 Self::resolve_fields_definition_types_and_directives(
543 indexed_type_definitions,
544 indexed_directive_definitions,
545 utd.fields_definition(),
546 errors,
547 );
548 utd.union_member_types().iter().for_each(|member_type| {
549 match indexed_type_definitions.get(member_type.name().as_ref()) {
550 Some(TypeDefinition::Object(_)) => {}
551 Some(_) => errors.push(
552 DefinitionDocumentError::ReferencedUnionMemberTypeIsNotAnObject {
553 name: member_type.name(),
554 },
555 ),
556 None => {
557 errors.push(DefinitionDocumentError::ReferencedTypeDoesNotExist {
558 name: member_type.name(),
559 })
560 }
561 }
562 });
563 Self::resolve_directive_definitions(indexed_directive_definitions, utd, errors);
564 }
565 TypeDefinition::InputObject(iotd) => {
566 Self::resolve_input_types_and_directives(
567 indexed_type_definitions,
568 indexed_directive_definitions,
569 iotd.input_field_definitions().iter(),
570 errors,
571 );
572
573 Self::resolve_directive_definitions(
574 indexed_directive_definitions,
575 iotd,
576 errors,
577 );
578 }
579 TypeDefinition::CustomScalar(cstd) => {
580 Self::resolve_directive_definitions(indexed_directive_definitions, cstd, errors)
581 }
582 TypeDefinition::Enum(etd) => {
583 Self::resolve_directive_definitions(indexed_directive_definitions, etd, errors);
584 etd.enum_value_definitions().iter().for_each(|evd| {
585 Self::resolve_directive_definitions(
586 indexed_directive_definitions,
587 evd,
588 errors,
589 );
590 });
591 }
592 TypeDefinition::BuiltinScalar(_) => {}
593 });
594
595 indexed_directive_definitions
596 .values()
597 .for_each(|directive_definition| {
598 if let Some(arguments_definition) = directive_definition.arguments_definition() {
599 Self::resolve_input_types_and_directives(
600 indexed_type_definitions,
601 indexed_directive_definitions,
602 arguments_definition.iter(),
603 errors,
604 );
605 }
606 })
607 }
608
609 fn resolve_fields_definition_types_and_directives(
610 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
611 indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
612 fields_definition: &'a FieldsDefinition<'a, C>,
613 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
614 ) {
615 fields_definition.iter().for_each(|field_definition| {
616 let t = field_definition.r#type().base();
617 match indexed_type_definitions.get(t.name().as_ref()) {
618 Some(&td) => match BaseOutputType::core_type_from_type_definition(td) {
619 Ok(_) => {}
620 Err(_) => {
621 errors.push(DefinitionDocumentError::ReferencedTypeIsNotAnOutputType {
622 name: t.name(),
623 })
624 }
625 },
626 None => errors
627 .push(DefinitionDocumentError::ReferencedTypeDoesNotExist { name: t.name() }),
628 }
629
630 if let Some(arguments_definition) = field_definition.arguments_definition() {
631 Self::resolve_input_types_and_directives(
632 indexed_type_definitions,
633 indexed_directive_definitions,
634 arguments_definition.iter(),
635 errors,
636 )
637 }
638
639 Self::resolve_directive_definitions(
640 indexed_directive_definitions,
641 field_definition,
642 errors,
643 );
644 })
645 }
646
647 fn resolve_interface_implementations(
648 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
649 interface_impelementations: &'a InterfaceImplementations<'a, C>,
650 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
651 ) {
652 interface_impelementations
653 .iter()
654 .for_each(|interface_implementation| {
655 let name = interface_implementation.interface_name();
656 match indexed_type_definitions.get(name.as_ref()) {
657 Some(TypeDefinition::Interface(_)) => {}
658 Some(_) => errors
659 .push(DefinitionDocumentError::ReferencedTypeIsNotAnInterface { name }),
660 None => {
661 errors.push(DefinitionDocumentError::ReferencedTypeDoesNotExist { name })
662 }
663 }
664 })
665 }
666
667 fn resolve_input_types_and_directives(
668 indexed_type_definitions: &BTreeMap<&str, &'a TypeDefinition<'a, C>>,
669 indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
670 input_value_definitions: impl Iterator<Item = &'a InputValueDefinition<'a, C>>,
671 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
672 ) {
673 input_value_definitions.for_each(|input_value_definition| {
674 let t = input_value_definition.r#type().base();
675 match indexed_type_definitions.get(t.name().as_ref()) {
676 Some(&td) => match BaseInputType::core_type_from_type_definition(td) {
677 Ok(_) => {}
678 Err(_) => {
679 errors.push(DefinitionDocumentError::ReferencedTypeIsNotAnInputType {
680 name: t.name(),
681 })
682 }
683 },
684 None => errors
685 .push(DefinitionDocumentError::ReferencedTypeDoesNotExist { name: t.name() }),
686 }
687
688 Self::resolve_directive_definitions(
689 indexed_directive_definitions,
690 input_value_definition,
691 errors,
692 );
693 })
694 }
695
696 fn resolve_directive_definitions(
697 indexed_directive_definitions: &BTreeMap<&str, &'a DirectiveDefinition<'a, C>>,
698 subject: &'a impl HasDirectives<Directives = Directives<'a, C>>,
699 errors: &mut Vec<DefinitionDocumentError<'a, C>>,
700 ) {
701 if let Some(directives) = subject.directives() {
702 directives.iter().for_each(|directive| {
703 match indexed_directive_definitions.get(directive.name()) {
704 Some(_) => {}
705 None => errors.push(DefinitionDocumentError::ReferencedDirectiveDoesNotExist {
706 directive,
707 }),
708 }
709 })
710 }
711 }
712}
713
714impl<'a, C: Context> TryFrom<&'a DefinitionDocument<'a, C>> for SchemaDefinition<'a, C> {
715 type Error = Vec<DefinitionDocumentError<'a, C>>;
716
717 fn try_from(definition_document: &'a DefinitionDocument<'a, C>) -> Result<Self, Self::Error> {
718 let mut errors = Vec::new();
719
720 let indexed_type_definitions = definition_document.index_type_definitions(&mut errors);
721
722 let indexed_directive_definitions =
723 definition_document.index_directive_definitions(&mut errors);
724
725 DefinitionDocument::resolve_type_and_directive_definitions(
726 &indexed_type_definitions,
727 &indexed_directive_definitions,
728 &mut errors,
729 );
730
731 if !errors.is_empty() {
732 return Err(errors);
733 }
734
735 if let Some((explicit, query, mutation, subscription)) =
736 definition_document.explicit_schema_definition(&indexed_type_definitions)?
737 {
738 return Ok(Self::new(
739 indexed_type_definitions,
740 indexed_directive_definitions,
741 explicit.description(),
742 query,
743 mutation,
744 subscription,
745 explicit.directives(),
746 ));
747 }
748
749 match DefinitionDocument::implicit_schema_definition(&indexed_type_definitions)? {
750 Some(implicit) => Ok(Self::new(
751 indexed_type_definitions,
752 indexed_directive_definitions,
753 None,
754 implicit.query,
755 implicit.mutation,
756 implicit.subscription,
757 None,
758 )),
759 None => Err(vec![DefinitionDocumentError::NoSchemaDefinition]),
760 }
761 }
762}
763
764#[cfg(test)]
765mod tests {
766 use std::collections::HashSet;
767
768 use bluejay_core::{
769 definition::{
770 FieldDefinition as CoreFieldDefinition,
771 ObjectTypeDefinition as CoreObjectTypeDefinition,
772 SchemaDefinition as CoreSchemaDefinition,
773 },
774 AsIter,
775 };
776
777 use super::{DefinitionDocument, Parse, SchemaDefinition};
778
779 #[test]
780 fn test_can_be_used_owned_with_self_cell() {
781 self_cell::self_cell!(
782 struct OwnedDefinitionDocument {
783 owner: String,
784
785 #[covariant]
786 dependent: DefinitionDocument,
787 }
788 );
789
790 self_cell::self_cell!(
791 struct OwnedSchemaDefinition {
792 owner: OwnedDefinitionDocument,
793
794 #[covariant]
795 dependent: SchemaDefinition,
796 }
797 );
798
799 let source = r#"
800 """
801 Description
802 """
803 type Query {
804 foo: String!
805 }
806 "#
807 .to_string();
808
809 let owned_definition_document = OwnedDefinitionDocument::new(source, |source| {
810 DefinitionDocument::parse(source).unwrap()
811 });
812
813 let owned_schema_definition =
814 OwnedSchemaDefinition::new(owned_definition_document, |owned_definition_document| {
815 SchemaDefinition::try_from(owned_definition_document.borrow_dependent()).unwrap()
816 });
817
818 let schema_definition = owned_schema_definition.borrow_dependent();
819
820 assert_eq!("Query", schema_definition.query().name().as_str());
821 }
822
823 #[test]
824 fn smoke_test() {
825 let s = r#"
826 """
827 Description
828 """
829 type Object {
830 foo: String!
831 }
832 "#;
833
834 let document: DefinitionDocument = DefinitionDocument::parse(s).unwrap();
835
836 assert_eq!(1, document.definition_count());
837 }
838
839 #[test]
840 fn builtin_fields_and_types_test() {
841 let s = r#"
842 directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT
843
844 type Query {
845 foo: String!
846 }
847
848 type Mutation {
849 foo: String!
850 }
851 "#;
852
853 let document: DefinitionDocument =
854 DefinitionDocument::parse(s).expect("Document had parse errors");
855
856 let schema_definition = SchemaDefinition::try_from(&document)
857 .expect("Could not convert document to schema definition");
858
859 let query_root_builtin_fields: HashSet<&str> = schema_definition
860 .query()
861 .fields_definition()
862 .iter()
863 .filter_map(|fd| fd.is_builtin().then_some(fd.name()))
864 .collect();
865
866 assert_eq!(
867 HashSet::from(["__typename", "__schema", "__type"]),
868 query_root_builtin_fields,
869 );
870
871 let mutation_root = schema_definition
872 .mutation()
873 .expect("Schema definition did not have a mutation root");
874
875 let mutation_root_builtin_fields: HashSet<&str> = mutation_root
876 .fields_definition()
877 .iter()
878 .filter_map(|fd| fd.is_builtin().then_some(fd.name()))
879 .collect();
880
881 assert_eq!(HashSet::from(["__typename"]), mutation_root_builtin_fields);
882
883 let directives: HashSet<&str> = schema_definition
884 .directive_definitions()
885 .map(|dd| dd.name())
886 .collect();
887
888 assert!(
889 HashSet::from(["include", "skip", "deprecated", "specifiedBy", "oneOf"])
890 .is_subset(&directives)
891 );
892
893 let builtin_types: HashSet<&str> = schema_definition
894 .type_definitions()
895 .filter_map(|td| td.is_builtin().then_some(td.name()))
896 .collect();
897
898 assert_eq!(
899 HashSet::from([
900 "__TypeKind",
901 "__DirectiveLocation",
902 "__Schema",
903 "__Type",
904 "__Field",
905 "__InputValue",
906 "__EnumValue",
907 "__Directive",
908 "String",
909 "ID",
910 "Boolean",
911 "Int",
912 "Float",
913 ]),
914 builtin_types,
915 );
916 }
917}