DEV Community

Cover image for refinedev - hasura (nested/multiple query_root)
Lalu Arman Rozika
Lalu Arman Rozika

Posted on

refinedev - hasura (nested/multiple query_root)

Refinedev is a react library to build dashboard, admin, etc, just like react-admin. You can connect it to many databases, including hasura.

The connection process to hasura is pretty much straightforward. Except, when your hasura database has multiple or nested query_root. I was searching for hours on how to filter the graphql query response to feed refine component.

So, refine component expect your graphql data to be like this:

data: {
    ...yourData
}
Enter fullscreen mode Exit fullscreen mode

Meanwhile, if your hasura database has multiple/nested query_root, the query response will look like this:

data: {
    data: {
        ...yourData
    {
}
Enter fullscreen mode Exit fullscreen mode

I don't find any mention of this problem in the docs, and there's no mention of how to deal with it. It just assume your hasura database has only one query_root and not nested.

Anyways, after hours of frustration, I finally found how to filter the graphql response, which is adding responseMiddleware in the GraphQLClient.

refinedev and hasura integration

Now, after doing that, refine component will finally be satisfied. That's what I thought it will be. I was wrong, lol.

If you read refinedev docs on how to connect refine to hasura, you will find that you need to generate schema Type, and also Type for queries and mutations. The docs give step by step explanation on what to install.

Basically, the types will be generated from your graphql queries, which in my case includes the nested query_root. So, modifying the response is not enough, I need to modify the generated types as well!

The types is generated using cli tools, and there's no option to modify its output (it's what I found so far).

Good Ol' plain NodeJs to the rescue!

Create script.cjs, or name the file whatever you want, in your root directory. Here's the script:

const fs = require("fs");

const filePath = "./src/graphql/types.ts";

function removeQueryRoot(dir) {
  const txtFile = "./src/graphql/types.txt";
  fs.renameSync(dir, txtFile);

  fs.readFile(txtFile, "utf8", function (err, data) {
    //change xyz to your query_root name
    const fRemoved = data.replaceAll("xyz?: Types.Maybe<{", "");
    const lRemoved = fRemoved.replaceAll(" }> ", "");
    fs.writeFile(dir, lRemoved, function () {
      fs.unlink(txtFile, () => {
        console.log("OK");
      });
    });
    if (err) console.log(err);
  });
}

removeQueryRoot(filePath);
Enter fullscreen mode Exit fullscreen mode

Now, run that script after you generate your graphql types. If you chain the command with && operator in your package.json script, sometimes it won't work. So just run it after you run the command for generating the types.

node script.cjs

The script will modify your previously generated types which is by default located at ./src/graphql/types.ts.

And that's it. Anything else, any other setup, you can find on refine dev documentation.

Top comments (0)