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

[FEAT] Default GraphQL DataProvider cannot function on deeper graphs #5943

Open
jamesdh opened this issue May 12, 2024 · 2 comments
Open

[FEAT] Default GraphQL DataProvider cannot function on deeper graphs #5943

jamesdh opened this issue May 12, 2024 · 2 comments
Labels
enhancement New feature or request

Comments

@jamesdh
Copy link

jamesdh commented May 12, 2024

Is your feature request related to a problem? Please describe.

Currently, the default GraphQL DataProvider is not capable of handling complex object graphs (which is very common in GraphQL). It appears to make the assumption that any query will be designed such that it returns the intended data type at the root level of the response. But this is very frequently not the case with GraphQL.

E.g.

query {
  userPosts(userId: 'me') {
    id
    title
    content
  }
}

But as is typically the case with GraphQL endpoints, they may not expose highly focused queries such as that, and you may have something along the lines of this, which is still very simplistic but contains the desired data only a single level deeper.

query {
  user(userId: 'me') {
    posts {
      id
      title
      content
    }
  }
}

Unfortunately this is not possible with the current DataProvider.

Describe alternatives you've considered

I propose amending the GraphQLQueryOptions type with a gqlDataPath and a gqlCountPath properties. These would be an array of strings that tell the DataProvider how to reach the intended data from the response.

An additional utils function could be added that would then take this path (if provided) and extract the intended object(s) for use in the response, e.g...

const getProp = (obj: any, path: (string | number)[], defaultValue: any = undefined): any =>
  path.reduce((acc: any, key: string | number) => acc && acc[key] !== undefined ? acc[key] : defaultValue, obj);

Then the returned result could be derived as so...

return {
  data: meta?.gqlDataPath ? getProp(meta.gqlDataPath) : response[operation],
  total: meta?.gqlCountPath ? getProp(meta.gqlCountPath): response[operation].count
}

Additional context

No response

Describe the thing to improve

This gives the default GraphQL DataProvider the ability to handle more than the most basic of response types. In my experience, one of the primary purposes of graphQL is to expose deeper, more complex graphs of data precisely because the data owners may not be aware of how clients intend to use it. It's likely not possible to expose rudimentary endpoints for every possible use case. GitHub's GraphQL endpoint is an excellent example of this.

@jamesdh jamesdh added the enhancement New feature or request label May 12, 2024
@BatuhanW
Copy link
Member

Hey @jamesdh this sounds like a good idea in general. I'm not sure about extracting multiple objects into a single response, because that would cache different responses into same resource key.

Would you like to work on this?

@jamesdh
Copy link
Author

jamesdh commented May 21, 2024

@BatuhanW already have to some degree, and also includes a solution to #5942. I'll get it cleaned up and create a draft PR for others to take a look at sometime this week or coming weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants