test-shisho-datasource 0.1.0

This is the utility for Shisho Cloud Policy SDK.
Documentation
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 {}

/// This struct contains the parameters necessary to generate code for a given operation.
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> {
    /// Generate the items for the variables and the response that will go inside the module.
    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(),
            })
    }

    /// Generate the module and all the code inside.
    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
            }
        ))
    }
}