2020-03-03 11:15:18 +00:00
|
|
|
use crate::model::{__EnumValue, __Field, __InputValue, __TypeKind};
|
2020-03-05 06:23:55 +00:00
|
|
|
use crate::registry;
|
2020-03-03 11:15:18 +00:00
|
|
|
use crate::registry::Type;
|
|
|
|
use async_graphql_derive::Object;
|
|
|
|
|
2020-03-04 06:24:44 +00:00
|
|
|
enum TypeDetail<'a> {
|
|
|
|
Simple(&'a registry::Type),
|
2020-03-05 13:34:31 +00:00
|
|
|
NonNull(String),
|
|
|
|
List(String),
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
|
|
|
|
2020-03-03 11:15:18 +00:00
|
|
|
pub struct __Type<'a> {
|
2020-03-04 06:24:44 +00:00
|
|
|
registry: &'a registry::Registry,
|
|
|
|
detail: TypeDetail<'a>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> __Type<'a> {
|
|
|
|
pub fn new_simple(registry: &'a registry::Registry, ty: &'a registry::Type) -> __Type<'a> {
|
|
|
|
__Type {
|
|
|
|
registry,
|
|
|
|
detail: TypeDetail::Simple(ty),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new(registry: &'a registry::Registry, type_name: &str) -> __Type<'a> {
|
|
|
|
if let Some(type_name) = parse_non_null(type_name) {
|
|
|
|
__Type {
|
|
|
|
registry,
|
2020-03-05 13:34:31 +00:00
|
|
|
detail: TypeDetail::NonNull(type_name.to_string()),
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
|
|
|
} else if let Some(type_name) = parse_list(type_name) {
|
|
|
|
__Type {
|
|
|
|
registry,
|
2020-03-05 13:34:31 +00:00
|
|
|
detail: TypeDetail::List(type_name.to_string()),
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
__Type {
|
|
|
|
registry,
|
|
|
|
detail: TypeDetail::Simple(®istry.types[type_name]),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[Object(
|
|
|
|
internal,
|
|
|
|
desc = r#"
|
|
|
|
The fundamental unit of any GraphQL Schema is the type. There are many kinds of types in GraphQL as represented by the `__TypeKind` enum.
|
|
|
|
|
|
|
|
Depending on the kind of a type, certain fields describe information about that type. Scalar types provide no information beyond a name and description, while Enum types provide their values. Object and Interface types provide the fields they describe. Abstract types, Union and Interface, provide the Object types possible at runtime. List and NonNull types compose other types.
|
|
|
|
"#
|
|
|
|
)]
|
|
|
|
impl<'a> __Type<'a> {
|
|
|
|
#[field]
|
|
|
|
async fn kind(&self) -> __TypeKind {
|
2020-03-04 06:24:44 +00:00
|
|
|
match &self.detail {
|
2020-03-05 06:23:55 +00:00
|
|
|
TypeDetail::Simple(ty) => match ty {
|
2020-03-04 06:24:44 +00:00
|
|
|
registry::Type::Scalar { .. } => __TypeKind::SCALAR,
|
|
|
|
registry::Type::Object { .. } => __TypeKind::OBJECT,
|
|
|
|
registry::Type::Interface { .. } => __TypeKind::INTERFACE,
|
|
|
|
registry::Type::Union { .. } => __TypeKind::UNION,
|
|
|
|
registry::Type::Enum { .. } => __TypeKind::ENUM,
|
|
|
|
registry::Type::InputObject { .. } => __TypeKind::INPUT_OBJECT,
|
2020-03-05 06:23:55 +00:00
|
|
|
},
|
|
|
|
TypeDetail::NonNull(_) => __TypeKind::NON_NULL,
|
|
|
|
TypeDetail::List(_) => __TypeKind::LIST,
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field]
|
|
|
|
async fn name(&self) -> Option<String> {
|
2020-03-04 06:24:44 +00:00
|
|
|
match &self.detail {
|
2020-03-05 06:23:55 +00:00
|
|
|
TypeDetail::Simple(ty) => match ty {
|
2020-03-04 06:24:44 +00:00
|
|
|
registry::Type::Scalar { name, .. } => Some(name.clone()),
|
|
|
|
registry::Type::Object { name, .. } => Some(name.to_string()),
|
|
|
|
registry::Type::Interface { name, .. } => Some(name.to_string()),
|
|
|
|
registry::Type::Union { name, .. } => Some(name.to_string()),
|
|
|
|
registry::Type::Enum { name, .. } => Some(name.to_string()),
|
|
|
|
registry::Type::InputObject { name, .. } => Some(name.to_string()),
|
2020-03-05 06:23:55 +00:00
|
|
|
},
|
|
|
|
TypeDetail::NonNull(_) => None,
|
|
|
|
TypeDetail::List(_) => None,
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field]
|
|
|
|
async fn description(&self) -> Option<String> {
|
2020-03-04 06:24:44 +00:00
|
|
|
match &self.detail {
|
2020-03-05 06:23:55 +00:00
|
|
|
TypeDetail::Simple(ty) => match ty {
|
2020-03-04 06:24:44 +00:00
|
|
|
registry::Type::Scalar { description, .. } => description.map(|s| s.to_string()),
|
|
|
|
registry::Type::Object { description, .. } => description.map(|s| s.to_string()),
|
|
|
|
registry::Type::Interface { description, .. } => description.map(|s| s.to_string()),
|
|
|
|
registry::Type::Union { description, .. } => description.map(|s| s.to_string()),
|
|
|
|
registry::Type::Enum { description, .. } => description.map(|s| s.to_string()),
|
|
|
|
registry::Type::InputObject { description, .. } => {
|
|
|
|
description.map(|s| s.to_string())
|
|
|
|
}
|
2020-03-05 06:23:55 +00:00
|
|
|
},
|
|
|
|
TypeDetail::NonNull(_) => None,
|
|
|
|
TypeDetail::List(_) => None,
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field]
|
|
|
|
async fn fields(
|
|
|
|
&self,
|
|
|
|
#[arg(name = "includeDeprecated", default = "false")] include_deprecated: bool,
|
|
|
|
) -> Option<Vec<__Field<'a>>> {
|
2020-03-04 06:24:44 +00:00
|
|
|
if let TypeDetail::Simple(Type::Object { fields, .. }) = &self.detail {
|
2020-03-05 06:23:55 +00:00
|
|
|
Some(
|
2020-03-03 11:15:18 +00:00
|
|
|
fields
|
|
|
|
.iter()
|
|
|
|
.filter(|field| {
|
|
|
|
if include_deprecated {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
field.deprecation.is_none()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.map(|field| __Field {
|
|
|
|
registry: self.registry,
|
|
|
|
field,
|
|
|
|
})
|
|
|
|
.collect(),
|
2020-03-05 06:23:55 +00:00
|
|
|
)
|
2020-03-06 15:58:43 +00:00
|
|
|
} else if let TypeDetail::Simple(Type::Interface { fields, .. }) = &self.detail {
|
|
|
|
Some(
|
|
|
|
fields
|
|
|
|
.iter()
|
|
|
|
.filter(|field| {
|
|
|
|
if include_deprecated {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
field.deprecation.is_none()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.map(|field| __Field {
|
|
|
|
registry: self.registry,
|
|
|
|
field,
|
|
|
|
})
|
|
|
|
.collect(),
|
|
|
|
)
|
2020-03-03 11:15:18 +00:00
|
|
|
} else {
|
2020-03-05 06:23:55 +00:00
|
|
|
None
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field]
|
|
|
|
async fn interfaces(&self) -> Option<Vec<__Type<'a>>> {
|
2020-03-06 15:58:43 +00:00
|
|
|
if let TypeDetail::Simple(Type::Object { name, .. }) = &self.detail {
|
|
|
|
Some(
|
|
|
|
self.registry
|
|
|
|
.implements
|
|
|
|
.get(*name)
|
|
|
|
.unwrap_or(&Default::default())
|
|
|
|
.iter()
|
|
|
|
.map(|ty| __Type::new(self.registry, ty))
|
|
|
|
.collect(),
|
|
|
|
)
|
2020-03-05 09:06:14 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 07:50:57 +00:00
|
|
|
#[field(name = "possibleTypes")]
|
2020-03-05 06:23:55 +00:00
|
|
|
async fn possible_types(&self) -> Option<Vec<__Type<'a>>> {
|
2020-03-06 15:58:43 +00:00
|
|
|
if let TypeDetail::Simple(Type::Interface { possible_types, .. }) = &self.detail {
|
|
|
|
Some(
|
|
|
|
possible_types
|
|
|
|
.iter()
|
|
|
|
.map(|ty| __Type::new(self.registry, ty))
|
|
|
|
.collect(),
|
|
|
|
)
|
2020-03-08 01:21:29 +00:00
|
|
|
} else if let TypeDetail::Simple(Type::Union { possible_types, .. }) = &self.detail {
|
|
|
|
Some(
|
|
|
|
possible_types
|
|
|
|
.iter()
|
|
|
|
.map(|ty| __Type::new(self.registry, ty))
|
|
|
|
.collect(),
|
|
|
|
)
|
2020-03-06 15:58:43 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field(name = "enumValues")]
|
|
|
|
async fn enum_values(
|
|
|
|
&self,
|
|
|
|
#[arg(name = "includeDeprecated", default = "false")] include_deprecated: bool,
|
|
|
|
) -> Option<Vec<__EnumValue<'a>>> {
|
2020-03-04 06:24:44 +00:00
|
|
|
if let TypeDetail::Simple(Type::Enum { enum_values, .. }) = &self.detail {
|
2020-03-05 06:23:55 +00:00
|
|
|
Some(
|
2020-03-03 11:15:18 +00:00
|
|
|
enum_values
|
|
|
|
.iter()
|
|
|
|
.filter(|field| {
|
|
|
|
if include_deprecated {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
field.deprecation.is_none()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.map(|value| __EnumValue {
|
|
|
|
registry: self.registry,
|
|
|
|
value,
|
|
|
|
})
|
|
|
|
.collect(),
|
2020-03-05 06:23:55 +00:00
|
|
|
)
|
2020-03-03 11:15:18 +00:00
|
|
|
} else {
|
2020-03-05 06:23:55 +00:00
|
|
|
None
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field(name = "inputFields")]
|
|
|
|
async fn input_fields(&self) -> Option<Vec<__InputValue<'a>>> {
|
2020-03-04 06:24:44 +00:00
|
|
|
if let TypeDetail::Simple(Type::InputObject { input_fields, .. }) = &self.detail {
|
2020-03-05 06:23:55 +00:00
|
|
|
Some(
|
2020-03-03 11:15:18 +00:00
|
|
|
input_fields
|
|
|
|
.iter()
|
|
|
|
.map(|input_value| __InputValue {
|
|
|
|
registry: self.registry,
|
|
|
|
input_value,
|
|
|
|
})
|
|
|
|
.collect(),
|
2020-03-05 06:23:55 +00:00
|
|
|
)
|
2020-03-03 11:15:18 +00:00
|
|
|
} else {
|
2020-03-05 06:23:55 +00:00
|
|
|
None
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-05 06:23:55 +00:00
|
|
|
#[field(name = "ofType")]
|
|
|
|
async fn of_type(&self) -> Option<__Type<'a>> {
|
2020-03-04 06:24:44 +00:00
|
|
|
if let TypeDetail::List(ty) = &self.detail {
|
2020-03-05 13:34:31 +00:00
|
|
|
Some(__Type::new(self.registry, &ty))
|
2020-03-04 06:24:44 +00:00
|
|
|
} else if let TypeDetail::NonNull(ty) = &self.detail {
|
2020-03-05 13:34:31 +00:00
|
|
|
Some(__Type::new(self.registry, &ty))
|
2020-03-04 06:24:44 +00:00
|
|
|
} else {
|
2020-03-05 06:23:55 +00:00
|
|
|
None
|
2020-03-04 06:24:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_non_null(type_name: &str) -> Option<&str> {
|
|
|
|
if type_name.ends_with("!") {
|
|
|
|
Some(&type_name[..type_name.len() - 1])
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_list(type_name: &str) -> Option<&str> {
|
|
|
|
if type_name.starts_with("[") {
|
|
|
|
Some(&type_name[1..type_name.len() - 1])
|
|
|
|
} else {
|
|
|
|
None
|
2020-03-03 11:15:18 +00:00
|
|
|
}
|
|
|
|
}
|