-
Notifications
You must be signed in to change notification settings - Fork 163
Description
Hi,
I have been using this crate for more than a year in the client of a hobby project browser game. Love this crate, thanks a bunch for the great work!
One thing has been bothering me for a while. In the code generated for a query, is it possible to define an existing Rust enum to use for deserialization instead of generating a new one? I'm thinking of something akin to custom scalars, where any Rust object with the same name as the GraphQL type defined in the schema can be used, as long as it implements Deserialize
.
As far as I can tell, nothing like that is supported today, is that correct? I'm happy to dig into the code and see if I could come up with a PR as an implementation suggestion, if the maintainers of this crate think it would be a worthwhile feature to add.
Motivation
My motivation for this is the following.
I have several Rust enums defined in a crate that I import in the client and the server. The Rust enums are simple C-style enumerations without fields, hence I map them to GraphQL enums.
The server uses Juniper to generate and serve a GraphQL interface. Using the graphql_client_cli
, I create a schema.json
from a running backend instance. Then I generate the code for the queries. This generates new enum types for each query.
So far so good. But I want to use the same enum type in the client as used by the backend. Thus, I have to manually translate from the generate enum back to the original enum type. I have to do this for every query where the enum is used. When I add a enum variant, I have to change the translation code for all queries.
Being able to specify to deserialize into my Rust enum directly would save me a lot of boiler-plate code.
Example
Shared Rust enum used by client and server:
#[derive(Clone, Copy, Serialize, Deserialize)]
#[cfg_attr(feature = "backend", derive(juniper::GraphQLEnum))]
pub enum BuildingType {
Tree,
Temple,
}
Schema generated by Juniper:
{
"description": null,
"enumValues": [
{
"deprecationReason": null,
"description": null,
"isDeprecated": false,
"name": "TREE"
},
{
"deprecationReason": null,
"description": null,
"isDeprecated": false,
"name": "TEMPLE"
}
],
"fields": null,
"inputFields": null,
"interfaces": null,
"kind": "ENUM",
"name": "BuildingType",
"possibleTypes": null
},
Query:
query BuildingsQuery($village_id: Int!) {
village(villageId: $village_id) {
buildings {
id
buildingType
}
}
}
Manual translation I currently need to do:
impl Into<BuildingType> for &buildings_query::BuildingType {
fn into(self) -> BuildingType {
match self {
buildings_query::BuildingType::TREE => BuildingType::Tree,
buildings_query::BuildingType::TEMPLE => BuildingType::Temple,
buildings_query::BuildingType::Other(_) => panic!("Unexpected BuildingType"),
}
}
}