pub mod connect;
pub mod federation;
pub mod link;
pub mod tag;
use apollo_compiler::{
ast::{
DirectiveDefinition, EnumTypeDefinition, InputObjectTypeDefinition, ScalarTypeDefinition,
},
parser::Parser,
Node,
};
use connect::{CONNECT_SPECS_BY_VERSION, CONNECT_SPEC_NAME};
use federation::{FEDERATION_SPECS_BY_VERSION, FEDERATION_SPEC_NAME};
use link::{LINK_SPECS_BY_VERSION, LINK_SPEC_NAME};
use once_cell::sync::Lazy;
use std::{
collections::HashMap,
fmt::{Display, Formatter},
};
use tag::{TAG_SPECS_BY_VERSION, TAG_SPEC_NAME};
#[derive(Debug, Clone)]
pub struct SpecDirective {
pub node: Node<DirectiveDefinition>,
}
impl SpecDirective {
pub fn new(definition_text: &str, description: &str) -> SpecDirective {
let ast = Parser::new()
.parse_ast(
format!("\"\"\"\n{}\n\"\"\"\n{}", description, definition_text),
"directive.graphql",
)
.unwrap();
let node = ast.definitions[0]
.as_directive_definition()
.unwrap()
.clone();
SpecDirective { node }
}
}
impl Display for SpecDirective {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.node.fmt(f)
}
}
#[derive(Debug, Clone)]
pub struct SpecType<T> {
pub node: Node<T>,
}
impl SpecType<EnumTypeDefinition> {
pub fn new(definition_text: &str) -> SpecType<EnumTypeDefinition> {
let ast = Parser::new()
.parse_ast(definition_text, "type.graphql")
.unwrap();
let node = ast.definitions[0]
.as_enum_type_definition()
.unwrap()
.clone();
SpecType { node }
}
}
impl SpecType<InputObjectTypeDefinition> {
pub fn new(definition_text: &str) -> SpecType<InputObjectTypeDefinition> {
let ast = Parser::new()
.parse_ast(definition_text, "input_type.graphql")
.unwrap();
let node = ast.definitions[0]
.as_input_object_type_definition()
.unwrap()
.clone();
SpecType { node }
}
}
impl SpecType<ScalarTypeDefinition> {
pub fn new(name: &str) -> SpecType<ScalarTypeDefinition> {
let ast = Parser::new()
.parse_ast(format!("scalar {}", name), "scalar.graphql")
.unwrap();
let node = ast.definitions[0]
.as_scalar_type_definition()
.unwrap()
.clone();
SpecType { node }
}
}
impl<T: Display> Display for SpecType<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.node.fmt(f)
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum SpecStatus {
Deprecated,
Experimental,
Supported,
Latest,
}
type SpecTypeMap<T> = HashMap<String, T>;
#[derive(Debug, Clone)]
pub struct Spec {
pub scalars: SpecTypeMap<SpecType<ScalarTypeDefinition>>,
pub input_types: SpecTypeMap<SpecType<InputObjectTypeDefinition>>,
pub directives: SpecTypeMap<SpecDirective>,
pub enums: SpecTypeMap<SpecType<EnumTypeDefinition>>,
pub status: SpecStatus,
}
pub type SpecsByVersion = HashMap<String, Spec>;
pub type SpecVersionsByName = HashMap<String, SpecsByVersion>;
pub static KNOWN_SPECS: Lazy<SpecVersionsByName> = Lazy::new(|| {
HashMap::from([
(LINK_SPEC_NAME.to_string(), LINK_SPECS_BY_VERSION.clone()),
(
FEDERATION_SPEC_NAME.to_string(),
FEDERATION_SPECS_BY_VERSION.clone(),
),
(TAG_SPEC_NAME.to_string(), TAG_SPECS_BY_VERSION.clone()),
(
CONNECT_SPEC_NAME.to_string(),
CONNECT_SPECS_BY_VERSION.clone(),
),
])
});