use std::sync::Arc;
use apollo_at_link::database::links_metadata;
use apollo_at_link::link::Link;
use apollo_at_link::spec::{Identity, APOLLO_SPEC_DOMAIN};
use apollo_compiler::executable::{Directive, SelectionSet};
use apollo_compiler::Schema;
pub fn federation_link_identity() -> Identity {
Identity {
domain: APOLLO_SPEC_DOMAIN.to_string(),
name: "federation".to_string(),
}
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Key {
pub type_name: String,
selections: Option<Arc<SelectionSet>>,
}
impl Key {
pub fn selections(&self) -> Option<Arc<SelectionSet>> {
self.selections.clone()
}
pub(crate) fn from_directive_application(
type_name: &str,
directive: &Directive,
) -> Option<Key> {
directive
.arguments
.iter()
.find(|arg| arg.name == "fields")
.and_then(|arg| arg.value.as_str())
.map(|_value| Key {
type_name: type_name.to_string(),
selections: None,
})
}
}
pub fn federation_link(schema: &Schema) -> Arc<Link> {
links_metadata(schema)
.unwrap_or_default()
.unwrap_or_default()
.for_identity(&federation_link_identity())
.expect("The presence of the federation link should have been validated on construction")
}
pub fn key_directive_name(schema: &Schema) -> String {
federation_link(schema).directive_name_in_schema("key")
}
pub fn keys(schema: &Schema, type_name: &str) -> Vec<Key> {
let key_name = key_directive_name(schema);
if let Some(type_def) = schema.types.get(type_name) {
type_def
.directives()
.get_all(&key_name)
.filter_map(|directive| Key::from_directive_application(type_name, directive))
.collect()
} else {
vec![]
}
}