Skip to content

Quick conversion between GraphQL input types and GraphQL types #538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Altaks opened this issue Apr 24, 2025 · 1 comment
Open

Quick conversion between GraphQL input types and GraphQL types #538

Altaks opened this issue Apr 24, 2025 · 1 comment

Comments

@Altaks
Copy link

Altaks commented Apr 24, 2025

Hi,
I'm facing a weird issue about the input types generated by the GraphQL macro.
Lets say I already have the CardInfo type in my codebase (on the server side), and I use the CardInfo type in my _schema.graphql :

#[derive(/*... */, SimpleObject, InputObject)]
#[graphql(input_name = "CardInfosInput")]
pub struct CardInfos {
// ...
};

_schema.graphql

# ...
type MutationRoot {
  createCard(card: CardInfos!): CardId!
}
# ...

When I use a build script to generate a sdl back from this _schema.graphql which is in a different crate, it creates both a CardInfosInput input and a CardInfo type :

build.rs

let schema = Schema::build(QueryRoot {}, MutationRoot {}, SubscriptionRoot {}).finish();
let mut file = BufWriter::new(File::create(&generated_path)?);

writeln!(&mut file, "{}", schema.sdl())?;

server_sdl.graphql (the generated one)

type CardInfos {
  fullName: FullName!
  jobTitle: JobTitle!
  # ...
}

input CardInfosInput {
  fullName: FullName!
  jobTitle: JobTitle!
  # ...
}

Which forces me to use ...Input types in my GraphQL operations definitions

createCard.graphql

mutation CreateCard($card: CardInfosInput!) {
  createCard(card: $card)
}

This mutation is merged to the MutationRoot, and is defined as such :

#[derive(GraphQLQuery)]
#[graphql(schema_path = "server_sdl.graphql", query_path = "src/queries/createCard.graphql", response_derives = "Debug")]
pub struct CreateCard;

However during the implementation of the resolver of such operations, I figured out there was no way to convert X to XInput types using something like a From or Into trait, in order to only write something like :

pub async fn create_card(state: GraphqlState, card: CardInfos) -> anyhow::Result<CardId> {
  let schema = get_schema();
  let vars = create_card::Variables { card: card.into() };
  // ....
}
impl From<CardInfos> for crate::queries::create_card::CardInfosInput {
  fn from(value: CardInfos) -> Self {
    Self {
      full_name: value.full_name,
      job_title: value.job_title,
      // ...
    }
  }
}

Furthermore, when using nested types I have to write more and more boilerplate.

Is there a way to avoid doing such a thing ? Or maybe could this macro expansion behavior be improved in any way ?

The problem can be summarized as follows :

     (server)                          (client)
StructA => StructAInput => SDL => StructA / StructInputA

Is there a way to reuse backend structs ?

Thanks in advance !

@tomhoule
Copy link
Member

I'd say this is out of scope for this crate, but I am happy to discuss feature requests if there is an elegant mechanism we can implement to make From / Into impls less painful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants