Skip to content
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

Serialize queries into GraphQL #1000

Closed
Bobrokus opened this issue Aug 15, 2024 · 1 comment
Closed

Serialize queries into GraphQL #1000

Bobrokus opened this issue Aug 15, 2024 · 1 comment

Comments

@Bobrokus
Copy link
Contributor

I suggest adding a way to serialize queries into their original GraphQL code.

You can serialize an Operation but that requires building the query. This is a problem when the query accepts variables and overall adds unnecessary overhead.

In my case I have a BulkOperationRunMutation which runs a mutation in bulk. This query accepts mutation: String, the actual mutation that will be run, and a file with variables that will be passed to each instance of the mutation in Jsonl format.
My idea is to create a wrapper that takes in a QueryFragment, serializes it into a string, and passes it to BulkOperationRunMutation as the mutation argument.

Example:

Serialize this

#[derive(cynic::QueryVariables, Debug)]
pub struct DeleteProductVariables<'a> {
    pub input: ProductDeleteInput<'a>,
}

#[derive(cynic::QueryFragment, Debug)]
#[cynic(graphql_type = "Mutation", variables = "DeleteProductVariables")]
pub struct DeleteProduct {
    #[arguments(input: $input)]
    pub product_delete: Option<ProductDeletePayload>,
}

#[derive(cynic::QueryFragment, Debug)]
pub struct ProductDeletePayload {
    pub deleted_product_id: Option<cynic::Id>,
}

#[derive(cynic::InputObject, Debug)]
pub struct ProductDeleteInput<'a> {
    pub id: &'a cynic::Id,
}

into

mutation deleteProduct($input: ProductDeleteInput!) {
  productDelete(input: $input) {
    deletedProductId
  }
}
obmarg added a commit that referenced this issue Aug 21, 2024
#### Why are we making this change?

**Related to: #1000**

Before this change, the only way (from my research) to serialize queries
into their original GraphQL source was to build an `Operation` and
retrieve the `query` field. The problem is that some queries require
variables, which are unnecessary for serialization, and an overhead
caused by the unwanted `Operation` struct.

The serialization process was in place the whole time, it was just
inaccessible on its own, covered by the `build` method.

#### What effects does this change have?

Moves document building out into a standalone
`build_executable_document` function which can be called to construct a
document string without access to a live variables struct

---------

Co-authored-by: Graeme Coupar <graeme@turbofish.tech>
obmarg added a commit that referenced this issue Aug 23, 2024
#### Why are we making this change?

In #1000 & #1004 a user is wanting to build a query that doesn't make
use of variables without hardcoding the values of arguments. This is to
make use of [some shopify functionality][1] that requires you to submit
a query without variables.

My initial instinct was that this should be done externally to cynic,
but I did plan on documenting how. #1007 was added to cater to this - it
contained an example that used the `graphql-query` crate to post-process
a cynic query and inline all of the variables into arguments in the
query.

However, when writing this I discovered it's not quite as smooth as I'd
hoped: you can't just dump the variables into JSON and put those into
the query because enums are serialised as strings in JSON but enum
format in GraphQL. Being unable to use JSON means you're also unable to
dynamically look up variables from their names - you have to hardcode
every variable that you want to substitute. Which is pretty crap.

#### What effects does this change have?

This PR introduces a new `QueryVariableLiterals` trait & derive that
aims to help with this: it exposes a single function `get` that can be
passed the name of a variable and it will return the appropriate
`InputLiteral` for that variable.

This can be used to make a `graphql-query` based transform much nicer,
but it should also make it easy enough to add support for variable
inlining into cynic itself.

[1]: https://shopify.dev/docs/api/admin-graphql/2024-07/mutations/bulkoperationrunquery
@Bobrokus
Copy link
Contributor Author

✅ Implemented as cynic::queries::build_executable_document. See #1004

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

1 participant