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

Support for persisted queries? #88

Open
onionhammer opened this issue Dec 28, 2023 · 7 comments
Open

Support for persisted queries? #88

onionhammer opened this issue Dec 28, 2023 · 7 comments
Assignees

Comments

@onionhammer
Copy link

onionhammer commented Dec 28, 2023

Is your feature request related to a problem? Please describe.
It would be great if this library support persisted queries, which means the server already knows the query the client is sending, and the client merely passes an "id" in the query string (GET) or "id" in the body (POST) rather than a query in the body

Describe the solution you'd like
A way for graphClient.request to pass an id corresponding to a query, or an alternative graphClient.requestId() where the first arg is an ID rather than the query itself

Describe alternatives you've considered
Alternatively, the library could provide a way to customize how operations are serialized, instead of just a hard-coded JSON.stringify(...)

@lynxtaa
Copy link
Owner

lynxtaa commented Jan 5, 2024

Thanks for the suggestions @onionhammer !

I think it could be done by providing a custom fetch function? I see that approach suggested for graphql-request library graffle-js/graffle#269 (comment)

@onionhammer
Copy link
Author

onionhammer commented Jan 5, 2024

Thanks for the suggestions @onionhammer !

I think it could be done by providing a custom fetch function? I see that approach suggested for graphql-request library graffle-js/graffle#269 (comment)

Unless I'm mistaken, it can be done with a custom fetch, but then one might as well not even use this library at all because you would have to reimplement pretty much everything

Check out the PR please, it would greatly improve the flexibility while also still allowing a user to utilize the parts of this library that are great

@lynxtaa
Copy link
Owner

lynxtaa commented Jan 5, 2024

My suggestion is to run client.request() by passing the id string to it instead of query. Then deserialize the body in custom fetch function and serialize it again with id field. Something like this

async function customFetch(url, init) {
  const { query, ...rest } = JSON.parse(init.body)
  return fetch(url, { ...init, body:  JSON.stringify({  ...rest, id: query }) })
}

@onionhammer
Copy link
Author

onionhammer commented Jan 6, 2024

@lynxtaa This works if the body is JSON and not FormData, which is not guaranteed. What is your objection to making the serialization itself more flexible? Perhaps you have suggestions on how I can change the PR to be less objectionable?

@lynxtaa
Copy link
Owner

lynxtaa commented Jan 6, 2024

This works if the body is JSON and not FormData, which is not guaranteed

It's also possible to get an operations field if body is not a string but FormData.

What is your objection to making the serialization itself more flexible?

I'm really grateful for your desire to improve the dev experience of this library and happy that you're using it :) I will think on implementing something like hooks to make it more flexible. So that the list of supported options and complexity would not grow and it'll be easier to support and maintain.

I would suggest using a custom fetch function for now. I know this solution is far from great, sorry for that. I'll keep this issue opened

@onionhammer
Copy link
Author

Thank you for the suggestion, if it is not too inefficient, I will take your recommendation. Otherwise, I may just end up forking this library.

@onionhammer
Copy link
Author

Here is what this workaround/hack looks like to anyone curious:

  fetch: (url, init) => {
    // eslint-disable-next-line prefer-const
    let { body, ...rest } = init;

    if (body instanceof FormData) {
      const operationsString = body.get("operations");
      if (!operationsString)
        throw new Error("Missing operations");

      const operations = JSON.parse(operationsString as string);
      const id = operations.query;
      body.set("operations", JSON.stringify({ ...operations, query: undefined, id }));
    }
    else {
      const parsed = JSON.parse(body);

      if (parsed.query) {
        parsed.id = parsed.query;
        delete parsed.query;
      }

      body = JSON.stringify(parsed);
    }

    return fetch(url, { ...rest, body });
  },

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