Hasura + GraphQL Mesh = <3
Tags: graphql, hasura, zeitnow, heroku
Published: 2020-04-01 22:00:00

---
title: Hasura + GraphQL Mesh = <3
published: true
description: Extend Hasura's already powerful Remote Schemas feature with GraphQL Mesh. Only a few lines of config and you can query against Open API, Protobuf, and more.
tags: GraphQL, Hasura, Zeit Now, Heroku
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/rydxwmwum9q5s3z2wtz6.png
---

### The Tweet

Early last week while scrolling through [Twitter](https://twitter.com/stephengfriend), I had noticed a new tool announced to the world, it was [GraphQL Mesh](https://graphql-mesh.com/). Normally I would have just read a few comments and likely moved along. However, I am currently looking at ways for us to incorporate legacy endpoints in our architecture at work. So, I spent a few minutes looking over the documentation and through the codebase. I was blown away by the claims and had to prove to myself that it was too good to be true.

{% twitter 1242118500795236353 %}

I had already spent a couple of weekends familiarizing myself with [Hasura](https://hasura.io/). It seemed like a really great fit for a project I have been building at work for the past 6 months. We have a few GraphQL endpoints that exist within our organization but no sort of federation or "one graph to rule them" yet. We need a light amount of application data to be persisted, but most of our data is gathered from upstream providers; a mix of Protobuf, HTTP/REST-like, and GraphQL.

To date, we have been writing custom data sources that use these endpoints and, where necessary, massage the data to fit into a coherent graph. Much bike-shedding and yak shaving have been performed. Hasura felt almost too perfect of a fit, and while not far from perfect for us, it did have a few gotchas that left me searching for alternatives.

### Enter GraphQL Mesh

While remote schemas in Hasura appealed to me, almost immediately, I hadn't noticed this meant remote _GraphQL-only_ schemas. This was helpful for the couple of dispersed endpoints we have, But it didn't help resolve our needs for non-GraphQL endpoints. When I saw the tweet, referenced above, over the weekend, I immediately started digging deep into and trying to use GraphQL Mesh as a gateway to our legacy endpoints.

> _**Caution!**_
> GraphQL Mesh is an exciting new technology. As with all exciting new technologies, it may take time for the API surface to stabilize. I would not consider this to be _Production Ready_ by most organization's standards. Give it a 🌟 star or 🍴 fork [the repository on Github](https://github.com/Urigo/graphql-mesh), if you find it as interesting as I did.

The rest of this article is a walk-through and demonstration of the integration. If you'd like to see the code, you can find it on GitHub. I will need to build a better demo before it can be played with, but plan on doing that next.

If you'd like, you can also [follow me](https://github.com/stephengfriend) or check out my [example repository on GitHub](https://github.com/stephengfriend/hasura-mesh).

### Getting Started

**Pre-requisites**

* A free [Heroku Account](https://signup.heroku.com/)
* A free [Zeit Now Account](https://zeit.co/signup)
* A free [Weatherbit.io Api Key](https://www.weatherbit.io/account/create)
* Node.js 10+


1) Make a directory and initialize a new npm `package.json`

```
$ mkdir hasura-mesh && cd hasura-mesh
$ npm init
```

2) Add the dependencies we will require

> _**Heads Up**_
> At the time of publishing, an alpha dependency is required to [pass our config as an object](https://github.com/Urigo/graphql-mesh/issues/150), rather than read from the filesystem

```
$ npm install graphql apollo-server-micro @graphql-mesh/runtime@0.0.16-alpha-0383167.40+0383167 @graphql-mesh/openapi @graphql-mesh/graphql
```

3) Setup the folder structure

```
$ mkdir api
$ touch api/mesh.js
```

4) Add code to `api/mesh.js`

```js
// These are required to get the now cli to bundle them
import "@graphql-mesh/graphql"
import "@graphql-mesh/openapi"

import { getMesh, processConfig } from "@graphql-mesh/runtime";
import { ApolloServer } from "apollo-server-micro";

// In a production environment, we would want to secure this endpoint
export default async (req, res) => {

  // Literal config object replaces .meshrc.yaml for serverless
  const parsedConfig = await processConfig({
    "sources": [
      {
        "name": "Weather",
        "handler": {
          "openapi": {
            "source": "https://api.apis.guru/v2/specs/weatherbit.io/2.0.0/swagger.json"
          }
        }
      },
      {
        "name": "Location",
        "handler": {
          "graphql": {
            "endpoint": "https://api.everbase.co/graphql"
          }
        }
      }
    ]
  });

  const { schema, contextBuilder: context } = await getMesh(parsedConfig);

  return new ApolloServer({
    schema,
    context,
    introspection: true, // Required for Hasura Remote Schema introspection
    playground: true, // Optional: Default is `false` in production
  }).createHandler({ path: "/api/mesh" })(req, res);
};

export const config = {
  api: {
    bodyParser: false
  }
};
```

5) Deploy to Zeit Now

> _**Heads Up**_
> Zeit now requires a globally unique project name, so moving forward in this guide we will use `$projectName` in place of the one you choose during deploy. Replace all instances of `$projectName` with the literal value for your project name.

```
$ npx now
```

6) Confirm our mesh gateway is working

Open a browser and navigate to `https://$projectName.now.sh/api/mesh` and we should see a GraphQL Playground instance where we can test our mesh.

> _**Heads Up**_
> You will need your Weatherbit.io api key for this next step. Add the following object to the Query Variables tab at the bottom: `{ "apiKey": "your-weatherbit.io-api-key"}` replacing the value with your api key.

```graphql
query GraphQLMesh($apiKey: String!){
  docs: url(url: "https://graphql-mesh.com/docs/getting-started/introduction") {
    scheme
    host
    path
  }
  weather: getCurrentCityCityCountryCountry(city: "Tampa", country: "US", key: $apiKey) {
    tampa: data {
    	observedAt: obTime
      stateCode
      temp
      precip
    }
  }
}
```

Assuming everything is working as expected, you should see something similar to the following screenshot.

![Screenshot of GraphQL Playground with validation query and response](https://dev-to-uploads.s3.amazonaws.com/i/27v56yc2gmv81mad2ppv.png)

### Adding Hasura

At this point, we can use our new GraphQL Mesh gateway just like any other Apollo Server. But Hasura has some desirable features such as Events and Real-time subscriptions that would be great to make use of.

> _**Heads Up**_
> At the time of publishing, Hasura is unable to make top-level requests across schemas. This means that querying a top-level field created from the data schema and from a remote schema in the same request is not possible. Follow [this issue](https://github.com/hasura/graphql-engine/issues/1371) for updates to this limitation.

Luckily, the Hasura team has made available a very simple and guided Heroku deploy. For the sake of brevity, we will use this method. Just click the below button to start the process.

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/hasura/graphql-engine-heroku)

> _**Heads Up**_
> Zeit now requires a globally unique project name, so moving forward in this guide we will use `$projectName` in place of the one you choose during deploy. Replace all instances of `$projectName` with the literal value for your project name.

After our service is up and running, head on over to your sweet new Hasura console, located at `https://$appName.herokuapp.com`. You should see a view similar to the below screenshot.

![Hasura Console](https://dev-to-uploads.s3.amazonaws.com/i/zi14jl1mp0x7y03c4h1q.png)

### Adding data and verifying

In the Hasura Console, navigate to the Remote Schemas tab. Give your remote schema a name, for the url we will want to use `https://$projectName.now.sh/api/mesh` where `$projectName` is the name of our Zeit Now project.

Once our remote schema has been added, we can head back to the GraphiQL tab and test our new mesh. We'll use the same query from above to test the integration.

> _**Heads Up**_
> You will need your Weatherbit.io api key for this next step. Add the following object to the Query Variables tab at the bottom: `{ "apiKey": "your-weatherbit.io-api-key"}` replacing the value with your api key.

```graphql
query GraphQLMesh($apiKey: String!){
  docs: url(url: "https://graphql-mesh.com/docs/getting-started/introduction") {
    scheme
    host
    path
  }
  weather: getCurrentCityCityCountryCountry(city: "Tampa", country: "US", key: $apiKey) {
    tampa: data {
    	observedAt: obTime
      stateCode
      temp
      precip
    }
  }
}
```

Finally, as above, assuming everything was set up correctly we should receive a near-identical response through Hasura that we did via our GraphQL Mesh gateway. Below is an example of what you should see.

![Screenshot of GraphiQL Explorer with validation query and response](https://dev-to-uploads.s3.amazonaws.com/i/t8ukgkbwzs7a2ztopmmj.png)

### Congratulations!

At this point, you should have a fully functional Hasura instance on Heroku with a remote schema proxying a GraphQL Mesh gateway running on Zeit Now. Creating tables, events and real-time subscriptions are out of scope, given the time we have today. I plan to learn and share more about GraphQL Mesh in the coming weeks.

I hope you have found value in this short article. If you have found any issues with the above content, I would love to hear from you. Please reach out in the comments or find me on Twitter.