Added support for inline fragment
This commit is contained in:
parent
40edb87fe0
commit
b4edae7981
|
@ -37,6 +37,7 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
.unwrap_or_else(|| quote! {None});
|
||||
let mut registry_types = Vec::new();
|
||||
let mut possible_types = Vec::new();
|
||||
let mut inline_fragment_resolvers = Vec::new();
|
||||
|
||||
for field in &fields.unnamed {
|
||||
if let Type::Path(p) = &field.ty {
|
||||
|
@ -57,6 +58,14 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
possible_types.push(quote! {
|
||||
<#p as async_graphql::GQLType>::type_name().to_string()
|
||||
});
|
||||
inline_fragment_resolvers.push(quote! {
|
||||
if name == <#p as async_graphql::GQLType>::type_name() {
|
||||
if let #ident::#enum_name(obj) = self {
|
||||
#crate_name::do_resolve(ctx, obj, result).await?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return Err(Error::new_spanned(field, "Invalid type"));
|
||||
}
|
||||
|
@ -228,6 +237,14 @@ pub fn generate(interface_args: &args::Interface, input: &DeriveInput) -> Result
|
|||
}
|
||||
.with_position(field.position));
|
||||
}
|
||||
|
||||
async fn resolve_inline_fragment(&self, name: &str, ctx: &#crate_name::ContextSelectionSet<'_>, result: &mut #crate_name::serde_json::Map<String, serde_json::Value>) -> #crate_name::Result<()> {
|
||||
#(#inline_fragment_resolvers)*
|
||||
anyhow::bail!(#crate_name::QueryError::UnrecognizedInlineFragment {
|
||||
object: #gql_typename.to_string(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
|
|
|
@ -227,6 +227,13 @@ pub fn generate(object_args: &args::Object, item_impl: &mut ItemImpl) -> Result<
|
|||
}
|
||||
.with_position(field.position));
|
||||
}
|
||||
|
||||
async fn resolve_inline_fragment(&self, name: &str, ctx: &#crate_name::ContextSelectionSet<'_>, result: &mut #crate_name::serde_json::Map<String, serde_json::Value>) -> #crate_name::Result<()> {
|
||||
anyhow::bail!(#crate_name::QueryError::UnrecognizedInlineFragment {
|
||||
object: #gql_typename.to_string(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Ok(expanded.into())
|
||||
|
|
11
src/base.rs
11
src/base.rs
|
@ -28,6 +28,13 @@ pub trait GQLObject: GQLOutputValue {
|
|||
}
|
||||
|
||||
async fn resolve_field(&self, ctx: &Context<'_>, field: &Field) -> Result<serde_json::Value>;
|
||||
|
||||
async fn resolve_inline_fragment(
|
||||
&self,
|
||||
name: &str,
|
||||
ctx: &ContextSelectionSet<'_>,
|
||||
result: &mut serde_json::Map<String, serde_json::Value>,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait GQLInputObject: GQLInputValue {}
|
||||
|
@ -78,6 +85,8 @@ macro_rules! impl_scalar {
|
|||
#[async_trait::async_trait]
|
||||
impl<T: GQLObject + Send + Sync> GQLOutputValue for T {
|
||||
async fn resolve(value: &Self, ctx: &ContextSelectionSet<'_>) -> Result<serde_json::Value> {
|
||||
crate::resolver::do_resolve(ctx, value).await
|
||||
let mut result = serde_json::Map::<String, serde_json::Value>::new();
|
||||
crate::resolver::do_resolve(ctx, value, &mut result).await?;
|
||||
Ok(result.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,12 @@ pub enum QueryError {
|
|||
|
||||
#[error("Unknown fragment \"{name}\".")]
|
||||
UnknownFragment { name: String },
|
||||
|
||||
#[error("Object \"{object}\" does not implement interface \"{interface}\"")]
|
||||
NotImplementedInterface { object: String, interface: String },
|
||||
|
||||
#[error("Unrecognized inline fragment \"{name}\" on type \"{object}\"")]
|
||||
UnrecognizedInlineFragment { object: String, name: String },
|
||||
}
|
||||
|
||||
pub trait ErrorWithPosition {
|
||||
|
|
|
@ -91,3 +91,5 @@ pub type Error = anyhow::Error;
|
|||
pub use context::ContextSelectionSet;
|
||||
#[doc(hidden)]
|
||||
pub mod registry;
|
||||
#[doc(hidden)]
|
||||
pub use resolver::do_resolve;
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{ContextSelectionSet, ErrorWithPosition, GQLObject, QueryError, Result};
|
||||
use graphql_parser::query::Selection;
|
||||
use graphql_parser::query::{Selection, TypeCondition};
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
|
@ -22,11 +22,11 @@ impl<'a, T: GQLObject + Send + Sync> Resolver<'a, T> {
|
|||
for selection in &self.ctx.item.items {
|
||||
match selection {
|
||||
Selection::Field(field) => {
|
||||
let ctx_field = self.ctx.with_item(field);
|
||||
if ctx_field.is_skip(&field.directives)? {
|
||||
if self.ctx.is_skip(&field.directives)? {
|
||||
continue;
|
||||
}
|
||||
|
||||
let ctx_field = self.ctx.with_item(field);
|
||||
if field.name.as_str() == "__typename" {
|
||||
self.result
|
||||
.insert(ctx_field.result_name(), T::type_name().to_string().into());
|
||||
|
@ -39,6 +39,10 @@ impl<'a, T: GQLObject + Send + Sync> Resolver<'a, T> {
|
|||
);
|
||||
}
|
||||
Selection::FragmentSpread(fragment_spread) => {
|
||||
if self.ctx.is_skip(&fragment_spread.directives)? {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(fragment) =
|
||||
self.ctx.fragments.get(&fragment_spread.fragment_name)
|
||||
{
|
||||
|
@ -56,7 +60,23 @@ impl<'a, T: GQLObject + Send + Sync> Resolver<'a, T> {
|
|||
.into());
|
||||
}
|
||||
}
|
||||
Selection::InlineFragment(_) => {}
|
||||
Selection::InlineFragment(inline_fragment) => {
|
||||
if self.ctx.is_skip(&inline_fragment.directives)? {
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(TypeCondition::On(name)) = &inline_fragment.type_condition {
|
||||
self.obj
|
||||
.resolve_inline_fragment(
|
||||
&name,
|
||||
&self.ctx.with_item(&inline_fragment.selection_set),
|
||||
self.result,
|
||||
)
|
||||
.await?;
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,16 +88,14 @@ impl<'a, T: GQLObject + Send + Sync> Resolver<'a, T> {
|
|||
pub async fn do_resolve<'a, T: GQLObject + Send + Sync>(
|
||||
ctx: &'a ContextSelectionSet<'a>,
|
||||
root: &'a T,
|
||||
) -> Result<serde_json::Value> {
|
||||
let mut result = serde_json::Map::<String, serde_json::Value>::new();
|
||||
|
||||
result: &mut serde_json::Map<String, serde_json::Value>,
|
||||
) -> Result<()> {
|
||||
Resolver {
|
||||
ctx,
|
||||
obj: root,
|
||||
result: &mut result,
|
||||
result,
|
||||
}
|
||||
.resolve()
|
||||
.await?;
|
||||
|
||||
Ok(serde_json::Value::Object(result))
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{registry, Context, GQLObject, GQLType, QueryError, Result};
|
||||
use crate::{registry, Context, ContextSelectionSet, GQLObject, GQLType, QueryError, Result};
|
||||
use graphql_parser::query::Field;
|
||||
use serde_json::{Map, Value};
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub struct GQLEmptyMutation;
|
||||
|
@ -27,4 +28,13 @@ impl GQLObject for GQLEmptyMutation {
|
|||
async fn resolve_field(&self, _ctx: &Context<'_>, _name: &Field) -> Result<serde_json::Value> {
|
||||
return Err(QueryError::NotConfiguredMutations.into());
|
||||
}
|
||||
|
||||
async fn resolve_inline_fragment(
|
||||
&self,
|
||||
_name: &str,
|
||||
_ctx: &ContextSelectionSet<'_>,
|
||||
_result: &mut Map<String, Value>,
|
||||
) -> Result<()> {
|
||||
return Err(QueryError::NotConfiguredMutations.into());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::model::{__Schema, __Type};
|
||||
use crate::{
|
||||
registry, Context, ErrorWithPosition, GQLObject, GQLOutputValue, GQLType, Result, Value,
|
||||
registry, Context, ContextSelectionSet, ErrorWithPosition, GQLObject, GQLOutputValue, GQLType,
|
||||
QueryError, Result, Value,
|
||||
};
|
||||
use graphql_parser::query::Field;
|
||||
use std::borrow::Cow;
|
||||
|
@ -52,4 +53,16 @@ impl<T: GQLObject + Send + Sync> GQLObject for QueryRoot<T> {
|
|||
|
||||
return self.inner.resolve_field(ctx, field).await;
|
||||
}
|
||||
|
||||
async fn resolve_inline_fragment(
|
||||
&self,
|
||||
name: &str,
|
||||
_ctx: &ContextSelectionSet<'_>,
|
||||
_result: &mut serde_json::Map<String, serde_json::Value>,
|
||||
) -> Result<()> {
|
||||
anyhow::bail!(QueryError::UnrecognizedInlineFragment {
|
||||
object: T::type_name().to_string(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user