Skip to content

Quick conversion between GraphQL input types and GraphQL types #538

Open
@Altaks

Description

@Altaks

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 !

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions