use crate::gqlgen::{
query::{BoundQuery, OperationId},
BoxError
};
use heck::*;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use std::{error::Error, fmt::Display};
#[derive(Debug)]
struct OperationNotFound {
operation_name: String,
}
impl Display for OperationNotFound {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("Could not find an operation named ")?;
f.write_str(&self.operation_name)?;
f.write_str(" in the query document.")
}
}
impl Error for OperationNotFound {}
pub(crate) struct GeneratedModule<'a> {
pub operation: &'a str,
pub resolved_query: &'a crate::gqlgen::query::Query,
pub schema: &'a crate::gqlgen::schema::Schema,
pub options: &'a crate::gqlgen::GraphQLClientCodegenOptions,
}
impl<'a> GeneratedModule<'a> {
fn build_impls(&self) -> Result<TokenStream, BoxError> {
Ok(crate::gqlgen::codegen::response_for_query(
self.root()?,
self.options,
BoundQuery {
query: self.resolved_query,
schema: self.schema,
},
)?)
}
fn root(&self) -> Result<OperationId, OperationNotFound> {
let op_name = self.options.normalization().operation(self.operation);
self.resolved_query
.select_operation(&op_name, *self.options.normalization())
.map(|op| op.0)
.ok_or_else(|| OperationNotFound {
operation_name: op_name.into(),
})
}
pub(crate) fn to_token_stream(&self) -> Result<TokenStream, BoxError> {
let module_name = Ident::new(&self.operation.to_snake_case(), Span::call_site());
let module_visibility = &self.options.module_visibility();
let impls = self.build_impls()?;
Ok(quote!(
#module_visibility mod #module_name {
#![allow(dead_code)]
use std::result::Result;
#impls
}
))
}
}