async-graphql/src/model/type.rs

209 lines
7.2 KiB
Rust
Raw Normal View History

2020-03-03 11:15:18 +00:00
use crate::model::{__EnumValue, __Field, __InputValue, __TypeKind};
use crate::{registry, Context, Object};
2020-03-03 11:15:18 +00:00
enum TypeDetail<'a> {
Named(&'a registry::MetaType),
2020-03-05 13:34:31 +00:00
NonNull(String),
List(String),
}
2020-03-03 11:15:18 +00:00
pub struct __Type<'a> {
registry: &'a registry::Registry,
detail: TypeDetail<'a>,
}
impl<'a> __Type<'a> {
pub fn new_simple(registry: &'a registry::Registry, ty: &'a registry::MetaType) -> __Type<'a> {
__Type {
registry,
2020-04-20 06:37:28 +00:00
detail: TypeDetail::Named(ty),
}
}
pub fn new(registry: &'a registry::Registry, type_name: &str) -> __Type<'a> {
match registry::MetaTypeName::create(type_name) {
registry::MetaTypeName::NonNull(ty) => __Type {
registry,
2020-03-08 12:35:36 +00:00
detail: TypeDetail::NonNull(ty.to_string()),
},
registry::MetaTypeName::List(ty) => __Type {
registry,
2020-03-08 12:35:36 +00:00
detail: TypeDetail::List(ty.to_string()),
},
registry::MetaTypeName::Named(ty) => __Type {
registry,
2020-04-20 06:37:28 +00:00
detail: TypeDetail::Named(&registry.types[ty]),
2020-03-08 12:35:36 +00:00
},
}
}
2020-03-03 11:15:18 +00:00
}
/// 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.
2020-10-14 09:08:57 +00:00
#[Object(internal, name = "__Type")]
2020-03-05 06:23:55 +00:00
impl<'a> __Type<'a> {
async fn kind(&self) -> __TypeKind {
match &self.detail {
2020-04-20 06:37:28 +00:00
TypeDetail::Named(ty) => match ty {
registry::MetaType::Scalar { .. } => __TypeKind::Scalar,
registry::MetaType::Object { .. } => __TypeKind::Object,
registry::MetaType::Interface { .. } => __TypeKind::Interface,
registry::MetaType::Union { .. } => __TypeKind::Union,
registry::MetaType::Enum { .. } => __TypeKind::Enum,
registry::MetaType::InputObject { .. } => __TypeKind::InputObject,
2020-03-05 06:23:55 +00:00
},
2020-03-09 12:00:57 +00:00
TypeDetail::NonNull(_) => __TypeKind::NonNull,
TypeDetail::List(_) => __TypeKind::List,
}
2020-03-03 11:15:18 +00:00
}
async fn name(&self) -> Option<&str> {
match &self.detail {
TypeDetail::Named(ty) => Some(ty.name()),
2020-03-05 06:23:55 +00:00
TypeDetail::NonNull(_) => None,
TypeDetail::List(_) => None,
}
2020-03-03 11:15:18 +00:00
}
async fn description(&self) -> Option<&str> {
match &self.detail {
2020-04-20 06:37:28 +00:00
TypeDetail::Named(ty) => match ty {
registry::MetaType::Scalar { description, .. }
| registry::MetaType::Object { description, .. }
| registry::MetaType::Interface { description, .. }
| registry::MetaType::Union { description, .. }
| registry::MetaType::Enum { description, .. }
| registry::MetaType::InputObject { description, .. } => description.as_deref(),
2020-03-05 06:23:55 +00:00
},
TypeDetail::NonNull(_) => None,
TypeDetail::List(_) => None,
}
2020-03-03 11:15:18 +00:00
}
async fn fields(
2020-03-05 06:23:55 +00:00
&self,
ctx: &Context<'_>,
2020-09-28 09:44:00 +00:00
#[graphql(default = false)] include_deprecated: bool,
2020-03-05 06:23:55 +00:00
) -> Option<Vec<__Field<'a>>> {
2020-04-20 06:37:28 +00:00
if let TypeDetail::Named(ty) = &self.detail {
ty.fields().map(|fields| {
fields
2020-03-19 09:20:12 +00:00
.values()
.filter(|field| match &field.visible {
Some(f) => f(ctx),
None => true,
})
2020-03-19 09:20:12 +00:00
.filter(|field| {
(include_deprecated || field.deprecation.is_none())
&& !field.name.starts_with("__")
})
.map(|field| __Field {
registry: self.registry,
field,
})
2020-10-15 06:38:10 +00:00
.collect()
2020-03-08 12:35:36 +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
}
}
async fn interfaces(&self) -> Option<Vec<__Type<'a>>> {
if let TypeDetail::Named(registry::MetaType::Object { name, .. }) = &self.detail {
2020-03-06 15:58:43 +00:00
Some(
self.registry
.implements
2020-03-19 09:20:12 +00:00
.get(name)
2020-03-06 15:58:43 +00:00
.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
}
async fn possible_types(&self) -> Option<Vec<__Type<'a>>> {
if let TypeDetail::Named(registry::MetaType::Interface { possible_types, .. }) =
&self.detail
{
2020-03-06 15:58:43 +00:00
Some(
possible_types
.iter()
.map(|ty| __Type::new(self.registry, ty))
.collect(),
)
} else if let TypeDetail::Named(registry::MetaType::Union { possible_types, .. }) =
&self.detail
2020-03-19 09:20:12 +00:00
{
2020-03-08 01:21:29 +00:00
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
}
async fn enum_values(
2020-03-05 06:23:55 +00:00
&self,
ctx: &Context<'_>,
2020-09-28 09:44:00 +00:00
#[graphql(default = false)] include_deprecated: bool,
2020-03-05 06:23:55 +00:00
) -> Option<Vec<__EnumValue<'a>>> {
if let TypeDetail::Named(registry::MetaType::Enum { enum_values, .. }) = &self.detail {
2020-03-05 06:23:55 +00:00
Some(
2020-03-03 11:15:18 +00:00
enum_values
2020-03-08 12:35:36 +00:00
.values()
.filter(|value| match &value.visible {
Some(f) => f(ctx),
None => true,
})
.filter(|value| include_deprecated || value.deprecation.is_none())
2020-03-03 11:15:18 +00:00
.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
}
}
async fn input_fields(&self, ctx: &Context<'_>) -> Option<Vec<__InputValue<'a>>> {
if let TypeDetail::Named(registry::MetaType::InputObject { input_fields, .. }) =
&self.detail
{
2020-03-05 06:23:55 +00:00
Some(
2020-03-03 11:15:18 +00:00
input_fields
2020-04-05 08:00:26 +00:00
.values()
.filter(|input_value| match &input_value.visible {
Some(f) => f(ctx),
None => true,
})
2020-03-03 11:15:18 +00:00
.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
}
}
async fn of_type(&self) -> Option<__Type<'a>> {
if let TypeDetail::List(ty) = &self.detail {
2020-03-05 13:34:31 +00:00
Some(__Type::new(self.registry, &ty))
} else if let TypeDetail::NonNull(ty) = &self.detail {
2020-03-05 13:34:31 +00:00
Some(__Type::new(self.registry, &ty))
} else {
2020-03-05 06:23:55 +00:00
None
}
}
}