refinedev/refine

[FEAT] Passing arbitrary graphql variables to hasura dataProvider

tomoemon opened this issue · 7 comments

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

I am very pleased that gqlQuery allows us to perform arbitrary GraphQL Queries against hasura.
#5489

However, it is not possible to use hasura's powerful filters because only CrudFilter[] can be passed to filters in the useTable. It is also not possible to use variables type information generated by graphql codegen.

In my case.
Given a type with the relation User has many Books, I can write a query in hasura to get a list of Users who have 3 or more Books, which is not possible in the current CrudFilter.

Describe alternatives you've considered

added to the following line in hasura dataProvider.

        variables = {
          ...hasuraPagination,
          ...(hasuraSorting &&
            (namingConvention === "graphql-default"
              ? {
                orderBy: hasuraSorting,
              }
              : {
                order_by: hasuraSorting,
              })),
          ...(hasuraFilters && {
            where: hasuraFilters,
          }),
          ...(meta?.gqlVariables && meta?.gqlVariables), // added
        };

https://github.com/refinedev/refine/blob/master/packages/hasura/src/dataProvider/index.ts#L181

This allows the addition of any where condition supported by hasura, using type information hints, as follows.

  const { tableProps } = useTable<GetFieldsFromList<BlogPostsQuery>>({
    syncWithLocation: true,
    meta: {
      gqlQuery: BlogPostsDocument,
      gqlVariables: {
        where: {
          _and: [
            {
              title: {
                _ilike: "%test%",
              },
            }
          ],
        },
      } as BlogPostsQueryVariables, // generated type from graphql query
    },
  });

Additional context

No response

Describe the thing to improve

  • add gqlVariables?: any to GraphQLQueryOptions
    • Ideally, I would like to pass the type information generated from the graphql query by type parameter instead of any, but I can't think of a way to achieve that right now.
  • use meta.gqlVariables in getList, getMany of hasura dataProvider

Hello @tomoemon, thanks for the issue.

It seems like a good idea, but can you give me the GQL Query you want to generate so I can better understand the problem? Maybe we can make CrudFilter[] to support this.

@alicanerdurmaz Thank you for your response!

For example, I want to execute the following query

Trying to get a list of categories that have at least one Posts with the string "test" in the title.
If Posts is related to another type, I may add more nested filters. This is often the case when I want to filter the items to be displayed with complex business logic.

query Categories {
    categories(
        where: {
            posts_aggregate: {
                count: {
                    predicate: { _gte: 1 },
                    filter: {
                        content: { _ilike: "%test%" }
                    }
                }
            }
        }
    ) {
        id
        title
    }
}

schema

type Posts {
    id: ID!
    title: String!
    content: String!
    categories: Categories!
}

type Categories {
    id: ID!
    title: String!
    posts: [Posts!]!
    posts_aggregate: posts_aggregate!
}

In my opinion, such a condition would be too complex to add to the CrudFilter. Writing complex filter conditions without type completion may also cause bugs.

@tomoemon Thanks for the detailed explanation, we'll see what we can do.

Hey @tomoemon I think you should use meta.gqlQuery and meta.gqlMutation fields. There you can pass your GraphQL queries created with graphql-tag.

https://refine.dev/docs/data/packages/hasura/#usage-with-graphql-tag

@BatuhanW
I don't understand why it was closed.

Do you mean that I should put a specific filter condition directly on the where argument in the gql tagged query?
If so, I can use any filter in hasura, but then how do I give it a dynamic value?

image

Hey @tomoemon, you are right. I think we can accept extra meta.gqlVariables field in the hooks and pass it to the query variables inside data provider.

We are open to contributions for this. This feature can be applied to following packages:

  • @refinedev/hasura
  • @refinedev/graphql
  • @refinedev/nestjs-query