-
Notifications
You must be signed in to change notification settings - Fork 47
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
feat: extract document building from OperationBuilder #1004
Conversation
[+] OperationBuilder::serialize - moves the serialization part from the build method into its one. This allows you to serialize the QueryFragment without supplying variables.
✅ Deploy Preview for cynic-querygen-web canceled.
|
Hi @Bobrokus. Thanks for the PR, and sorry for the delay getting back to you - I've been on holiday the past couple of weeks. I'm definitely happy to support this use case, I don't think you're the first person that has wanted it. However, I'm not sure if OperationBuilder is the right place for this to live. Let me have a think and get back to you in the next day or two. |
Hey! I'm thrilled to hear this! I also don't think It's more of a proof of concept. It would be fantastic to see a more mature implementation, but I believe that would require knowledge of macros, which I currently lack. NOTE: I'm also thinking about splitting the serialization into 2 parts - variables & selection set - for more refined control. |
I don't think this requires any macro changes tbh. I think adding a free standing function in the
Where the implementation is very similar to what you have in
I'm not sure exactly what you mean by this - can you elaborate? |
Yea agree that seems reasonable.
I need to serialize the query with variables inline. Serialized string is made of |
I am struggling to see a use case for having the selection set separate from the variable definitions - have you got one in mind? |
Yes. Like I said - inline variables. I need to replace |
Why do you want to do that though? Can you give me an example? The variables defined in |
Unless of course by inlining you mean taking: query X(a: Int!, b: Int!) { foo(a: $a, b: $b) } and converting it to query X { foo(a: 1, b: 2) } Is that what you're trying to do? If so, I'd still be curious as to why? I'm not sure that getting access to the raw variable string would be the right way to go about doing that, so any more info on your use case would be great... |
Yep, that's exactly what I meant. Sorry, I thought you could do 'inline variables' query X(a: Int! = 1, b: Int! =2) but I realized those are just default values. Your way is much better and compact. |
Is there a way to convert this thread into an issue or a discussion? |
Ok, and you are proposing splitting up the generation of There might be a better way to get cynic to inline variables but it'd require a bit of API rework to achieve. Why is it that you can't just provide the variables in the request body? I understand why you might want to serialise a query string without having to provide variables but not why you'd want to avoid variables altogether |
I don't believe there's a way to convert it. I am fine continuing here, but if you want to create an issue and/or discussion for this new request feel free. |
Nope, I don't mind if you don't. Just want to point out #1000 |
@obmarg so what do you think about the inline arguments? |
I'm still wondering why is it that you can't just provide the variables in the HTTP request body? In #1000 you say:
If there's a file you can pass in (which seems strange but ok) with the variables why don't you do that? Inlining variables into the query document seems like such a niche use case, given that variables are core to GraphQL and every single server & client supports them. I'd need a very strong motivating use case to consider adding support for it. I've been asking why a lot in order to try and get at that use case, but I don't feel like I've got an answer yet. |
Oh! I forgot to mention. In the Shopify GraphQL API, there's also I might be able to pull it off myself by replacing all occurrences of The reason |
Ok, I see - that is... quite an annoying design from shopify. Let me have a quick think about how best to solve this - I have some ideas but I need to mull them over a bit. |
OperationBuilder::serialize()
(non-Serde)
@Bobrokus I've cleaned up this PR into a state where I think it's mergable, and have some ideas for how to tackle the inlining you are after - however it's too late for me to write them out for you now. I'll get back to you about that bit tomorrow. |
Thanks so much! I truly appreciate it. See you tommorow. Btw, why not implement |
|
#### 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
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 thequery
field. The problem is that some queries require variables, which are unnecessary for serialization, and an overhead caused by the unwantedOperation
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