1use crate::{
2 error::GqlError,
3 types::{__Type, build_schema_introspection},
4 CollectFields, Context, FieldResolver, GqlValue, ResolverResult, SelectionSetResolver,
5};
6
7pub struct QueryRoot<T> {
8 pub query: T,
9}
10
11#[async_trait::async_trait]
12impl<T: SelectionSetResolver> FieldResolver for QueryRoot<T> {
13 async fn resolve_field(&self, ctx: &Context<'_>) -> ResolverResult<Option<GqlValue>> {
14 if ctx.item.name == "__schema" {
15 let ctx_selection_set = ctx.with_selection_set(&ctx.item.selection_set);
16 let schema_intro = build_schema_introspection(ctx.schema);
17 return schema_intro
18 .resolve_selection_set(&ctx_selection_set)
19 .await
20 .map(Some);
21 } else if ctx.item.name == "__type" {
22 let type_name = ctx.get_arg_value::<String>("name")?;
23 let ctx_selection_set = ctx.with_selection_set(&ctx.item.selection_set);
24 let ty = ctx_selection_set
25 .schema
26 .type_definitions
27 .get(&type_name)
28 .map(|ty| __Type::from_type_definition(ctx_selection_set.schema, ty));
29 match ty {
30 Some(intro_ty) => intro_ty
31 .resolve_selection_set(&ctx_selection_set)
32 .await
33 .map(Some),
34 None => Err(GqlError::new(format!("{} is not defined", type_name), None)),
35 }
36 } else {
37 self.query.resolve_field(ctx).await
38 }
39 }
40 fn type_name() -> String {
41 "Query".to_string()
42 }
43}
44
45impl<T: SelectionSetResolver> CollectFields for QueryRoot<T> {}
46
47#[async_trait::async_trait]
48impl<T: SelectionSetResolver> SelectionSetResolver for QueryRoot<T> {
49 async fn resolve_selection_set(
50 &self,
51 ctx: &crate::SelectionSetContext<'_>,
52 ) -> ResolverResult<GqlValue> {
53 self.query.resolve_selection_set(ctx).await
54 }
55}