question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[RFC] GraphQL adaptators improvements

See original GitHub issue

Hey there,

As of now, most GraphQL adaptators aren’t taking full advantage of one of GraphQL’s biggest benefit: being able to query nested fields in one request, as deep as the schema allow us to. Instead, they’re more or less imitating the way REST works, by making X request for X reference needed (although some great optimizations were already done in that regard https://marmelab.com/blog/2016/10/18/using-redux-saga-to-deduplicate-and-group-actions.html)

I think there are ways we could improve that, and I suggest we use this place as a central thread to discuss about what could be done.

Suggestion n°1

Include all scalar fields of linked types by default

As of now, we’re only fetching ids from linked types, which forces us to use <ReferenceField /> on every linked type.

const linkedResource = introspectionResults.resources.find(
  r => r.type.name === type.name
);

if (linkedResource) {
  return { ...acc, [field.name]: { fields: { id: {} } } };
}

One quick-fix that could be done, is to automatically fetch all scalar fields of linked types:

const linkedResource = introspectionResults.resources.find(r => r.type.name === type.name);

if (linkedResource) {
  // Fetch all linked resource scalar fields
  const linkedScalarFields = linkedResource.type.fields
    .filter(field => getFinalType(field.type).kind !== TypeKind.OBJECT)
    .reduce((acc, field) => ({ ...acc, [field.name]: {} }), {});

  return { ...acc, [field.name]: { fields: linkedScalarFields } };
}

This way, we’re able to use <TextField source="linkedType.scalarField" />, which already cover lots of cases and greatly improve the amount of request made. I think the few more bytes that those additional fields will take on every requests are more than worth the amount of request that it will save.

Suggestion n°2

Make this overridable

After thinking about it, @fzaninotto, I don’t think there’s a need for a function to transform the introspectionResults. The introspection query already fetches all the existing types (and their fields) anyway.

If I’m not mistaking, overriding the behavior described above is actually already possible and that’s what you’ve done here, by overriding the query that fetches the Command.

I think we could provide a simpler and more concise API to do that, for two reasons:

  • The query name and the params are not needed for what we’re trying to achieve. The params will always have to be declared anyway, and it can become heavy when overriding GET_LIST actions (having filters, sorting and pagination as input).

  • Users have to be careful about the aliases (data and sometimes total)

If you agree with me, I see two ways of enhancing this:

const COMMAND_FIELDS = `{
  id
  reference
  product { id name }
}`
  • By providing the same API as graphqlify expects (more consistent, but heavier IMO)

That’s all for now, tell me what you guys think 🙌

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:5
  • Comments:20 (20 by maintainers)

github_iconTop GitHub Comments

2reactions
Weakkycommented, Aug 31, 2018

Ok, I think I get what you’re doing now

You should’ve seen my smile reading those sweet words 😂

I think the overrideQueriesByFragment is cumbersome to use though. Taking your repository product as an example, I suggest doing something like the following

This is fine for me. Your way of doing it is more consistent as you’re planning to remove the override option. Everything will have to be done by decorating the provider, offering more freedom. I’ll be able to use my cumbersome data structure anyway to avoid those ugly if statements 😄

Besides, I assume the only thing we have to do on our side is to include the full schema in the introspectionResults so that you can validate fragments, etc. Right? We may then steal your code for our own providers

Exactly ! Let me recap everything:

  1. Remove the override option from ra-data-graphql
  2. Include the schema into the introspectionResults (other usecases might be found in the future)
  3. Adapt the current examples to showcase how queries can be overriden using fragments

I might find some time to send a few PR’s 🎉

2reactions
djhicommented, Aug 31, 2018

Ok, I think I get what you’re doing now. Basically, you want a way to override a query without having to write the query boilerplate with parameters, etc.

I think the overrideQueriesByFragment is cumbersome to use though. Taking your repository product as an example, I suggest doing something like the following:

// in src/buildDataProvider.js
import buildApolloClient, { buildQuery } from 'ra-data-graphcool';

const productGetListQuery = gql`
    fragment product on Product {
        id
        name
        description
        brand {
            id
            name
        }
        category {
            id
            name
        }
        shop {
            id
            name
        }
        attributes {
            id
            value
        }
    }
`; 
const myBuildQuery = buildQuery => (aorFetchType, resource, params) => {
    if (resource === 'Category' && aorFetchType === 'GET_ONE') {
        // buildQuery accepts an extra parameter which is the query/fragment to use as an override
        // The rest of your logic still applies but you wont have to find the override
        return buildQuery(aorFetchType, resource, params, productGetListQuery);
    }

    return buildQuery(aorFetchType, resource, params);
};

export default () => 
     buildApolloClient({ 
         clientOptions: { 
             uri: 'https://api.graph.cool/simple/v1/cj2kl5gbc8w7a0130p3n4eg78', 
         }, 
         buildQuery: myBuildQuery(buildQuery), 
    });

Besides, I assume the only thing we have to do on our side is to include the full schema in the introspectionResults so that you can validate fragments, etc. Right? We may then steal your code for our own providers 😛

Read more comments on GitHub >

github_iconTop Results From Across the Web

The next step for realtime data in GraphQL
In this article, we'll go over the backstory of how subscriptions came to be, what the proposal for subscriptions looks like, and how...
Read more >
Fetch Data Using the GraphQL Wire Adapter (Pilot)
Built on the Salesforce GraphQL API, the GraphQL wire adapter enables you to use UI API enabled objects with the object-level security and...
Read more >
Subscriptions and Live Queries - Real Time with GraphQL
The GraphQL Subscription RFC was merged back in March 2017. ... There are also adapters available for more distributed systems (where all ...
Read more >
GraphQL specification
GraphQL. June 2018 Edition. Introduction. This is the specification for GraphQL, a query language and execution engine originally created at Facebook in ...
Read more >
Protocol Adapters - SAP Capire
Query. Default Configuration; Protocol Annotations; Customization. OData V4; REST; GraphQL Adapter; Custom Protocol Adapter. Current Limitations. Default ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found