mod definitions;
mod directives;
mod enums;
mod extensions;
mod field_types;
mod fields;
mod ids;
mod keys;
mod linked_schemas;
mod strings;
mod top;
mod unions;
mod view;
pub(crate) use self::{
definitions::*, directives::*, enums::*, extensions::*, field_types::*, fields::*, ids::*, keys::*,
linked_schemas::*, strings::StringId, top::*, view::View,
};
use crate::VecExt;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
pub struct Subgraphs {
pub(super) strings: strings::Strings,
subgraphs: Vec<Subgraph>,
definitions: definitions::Definitions,
directives: directives::Directives,
enums: enums::Enums,
fields: fields::Fields,
keys: keys::Keys,
unions: unions::Unions,
linked_schemas: linked_schemas::LinkedSchemas,
ingestion_diagnostics: crate::Diagnostics,
extensions: Vec<ExtensionRecord>,
definition_names: BTreeMap<(StringId, SubgraphId), DefinitionId>,
}
impl Default for Subgraphs {
fn default() -> Self {
let mut strings = strings::Strings::default();
BUILTIN_SCALARS.into_iter().for_each(|scalar| {
strings.intern(scalar);
});
Self {
strings,
subgraphs: Default::default(),
definitions: Default::default(),
directives: Default::default(),
enums: Default::default(),
fields: Default::default(),
keys: Default::default(),
unions: Default::default(),
ingestion_diagnostics: Default::default(),
definition_names: Default::default(),
linked_schemas: Default::default(),
extensions: Vec::new(),
}
}
}
const BUILTIN_SCALARS: [&str; 5] = ["ID", "String", "Boolean", "Int", "Float"];
#[derive(Debug)]
pub struct IngestError {
error: cynic_parser::Error,
report: String,
}
impl std::error::Error for IngestError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.error.source()
}
}
impl std::fmt::Display for IngestError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if f.alternate() {
return self.report.fmt(f);
}
std::fmt::Display::fmt(&self.error, f)
}
}
impl Subgraphs {
pub fn ingest(&mut self, subgraph_schema: &cynic_parser::TypeSystemDocument, name: &str, url: Option<&str>) {
crate::ingest_subgraph::ingest_subgraph(subgraph_schema, name, url, self);
}
pub fn ingest_str(&mut self, subgraph_schema: &str, name: &str, url: Option<&str>) -> Result<(), IngestError> {
let subgraph_schema =
cynic_parser::parse_type_system_document(subgraph_schema).map_err(|error| IngestError {
report: error.to_report(subgraph_schema).to_string(),
error,
})?;
crate::ingest_subgraph::ingest_subgraph(&subgraph_schema, name, url, self);
Ok(())
}
#[doc(hidden)]
pub fn ingest_loaded_extensions(&mut self, extensions: impl IntoIterator<Item = crate::LoadedExtension>) {
self.extensions
.extend(extensions.into_iter().map(|ext| ExtensionRecord {
url: self.strings.intern(ext.url.as_str()),
link_url: self.strings.intern(ext.link_url.as_str()),
name: self.strings.intern(ext.name),
}));
}
pub fn is_empty(&self) -> bool {
self.subgraphs.is_empty()
}
pub(crate) fn iter_definition_groups<'a>(&'a self, mut compose_fn: impl FnMut(&[DefinitionView<'a>])) {
let mut key = None;
let mut buf = Vec::new();
for ((name, subgraph), definition) in &self.definition_names {
if Some(name) != key {
compose_fn(&buf);
buf.clear();
key = Some(name);
}
if self.is_root_type(*subgraph, *definition) {
continue; }
buf.push(self.at(*definition));
}
compose_fn(&buf)
}
pub(crate) fn push_ingestion_diagnostic(&mut self, subgraph: SubgraphId, message: String) {
self.ingestion_diagnostics
.push_fatal(format!("[{}]: {message}", self[self.at(subgraph).name]));
}
pub(crate) fn push_ingestion_warning(&mut self, subgraph: SubgraphId, message: String) {
self.ingestion_diagnostics
.push_warning(format!("[{}]: {message}", self[self.at(subgraph).name]));
}
pub(crate) fn iter_builtin_scalars(&self) -> impl ExactSizeIterator<Item = &str> + '_ {
BUILTIN_SCALARS.into_iter()
}
pub(crate) fn emit_ingestion_diagnostics(&self, diagnostics: &mut crate::Diagnostics) {
diagnostics.clone_all_from(&self.ingestion_diagnostics);
}
pub(crate) fn sort_pre_composition(&mut self) {
self.keys.keys.sort_unstable_by_key(|key| key.definition_id);
self.directives
.extra_directives
.sort_unstable_by_key(|directive| directive.directive_site_id);
self.enums
.values
.sort_unstable_by_key(|value| (value.parent_enum_id, value.name));
self.fields
.fields
.sort_unstable_by_key(|field| (field.parent_definition_id, field.name));
self.fields.arguments.sort_unstable_by_key(|argument| {
(argument.parent_definition_id, argument.parent_field_name, argument.name)
});
}
}