GraphQL is a dream for frontend developers and clients alike. After all, clients don’t care where data is coming from or what database format you’re using. They care about getting the data they’re asking for quickly, cleanly, and painlessly. Bonus points if it doesn’t put too heavy of a load on the server.
It’s been a goal for all APIs to be consumed in the GraphQL format,for developers who’ve grown accustomed to its simplicity and ease. That dream is now a reality thanks to a new library, GraphQL Mesh. GraphQL Mesh is a Rosetta Stone allowing all of your APIs and local databases to play nice together.
GraphQL Mesh is a new library created by The Guild, an open-source group dedicated to empowering developers to take advantage of the many benefits of GraphQL.
The Guild are also responsible for popular GraphQL resources like GraphQL Code Editor, GraphQL Inspector, and GraphQL-CLI. They clearly know a thing or two about making GraphQL available for a wide pool of different developers, regardless of whether or not they’re previously familiar with the specification created by Facebook.
GraphQL Mesh is a dream come true for developers who’ve been wanting to try GraphQL but have been reluctant due to either lack of experience or having legacy products in older formats like REST. GraphQL Mesh is designed to act as an intermediary layer to receive data from nearly anywhere and translate it into a GraphQL format.
The goal of GraphQL Mesh is to take data from a wide array of different formats and integrate them with GraphQL so they can be modified with GraphQL queries and mutations.
So far, GraphQL Mesh has native support for:
This makes it easy to modify output schema, link types across schema and merge schema types. It also gives you granular control over how you retrieve data, overcome backend limitations, as well as complications due to schema specifications and non-typed APIs.
GraphQL Mesh also acts as a proxy for your local data and lets you use common libraries with other APIs. You can use this proxy locally or you can call the service in other applications with an execute function.
Keep in mind that GraphQL Mesh is mainly intended as a background layer for your enterprise. If you want to serve the data to the public, you’ll most likely need to add an additional abstraction layer.
GraphQL starts by collecting API schemas from the services it communicates with. It then creates a runtime environment of fully-typed SDKs for those services. Then it translates various API specs into the GraphQL schema, where custom schema transformations and extensions can be performed. Finally, all of this is wrapped up into one SDK which is used to obtain data from the service you’re trying to communicate with.
This is achieved using local schema, which is created from the autogenerated directory when you install GraphQL Mesh.
This schema lets you use GraphQL’s execute function to run query and mutation functions locally in your application. This enables GraphQL to act as a central nervous system between your app and whatever you’re using to power it.
GraphQL allows clients and end users to integrate data of all kinds of different formats.
Users don’t need to have a thorough understanding of a complex API architecture to retrieve the data they need. It also makes rapid prototyping much quicker and more efficient since you don’t have to go under the hood of your API every time you want to make an insignificant change.
GraphQL is also much more efficient than other specifications like REST. REST returns all of the data stored in a database when it’s queried, which can result in overfetching and underfetching.
GraphQL only returns the exact data the user queries for. Not only does this save on resources, but it also makes an API easier to use since you spend less time looking for the data you need.
All of that data is returned to one place. While REST’s prolific use of endpoints definitely has its uses, it has its downsides as well. Having the ability to have all of that data routed to one endpoint is a major benefit and reason enough to give GraphQL Mesh a try in and of itself.
GraphQL Mesh translates APIs in nearly any given format into a GraphQL format. It’s an abstraction layer that can be overlaid nearly any source, including local files and databases.
GraphQL Mesh comes available as several packages which you can install depending on your particular needs. We’ll show you how to set up a basic instance of GraphQL Mesh so you can get started with the library and try it out yourself.
To start, you’re going to need to install the Yarn
package handler, which makes packages available globally. For the sake of good housekeeping, create a new directory for this project in your development folder. We’ve called ours GraphQL_mesh
.
In the root directory of your project folder, create a file called .meshrc.yaml
using a text editor of your choosing.
We’re using Notepad++, an open source text editor that lets you save files in whatever file format you want. Paste the following into the file and then save:
sources: - name: Wiki handler: openapi: source: https://api.apis.guru/v2/specs/wikimedia.org/1.0.0/swagger.yaml
Navigate to that directory using Terminal and input the following:
$ npm install yarn --global
To install the basic GraphQL Mesh package, type the following:
$ yarn add graphql @graphql-mesh/runtime @graphql-mesh/cli
Now you need to install a Mesh handler, depending on the needs of the specific API you’ll be using. For the sake of this example, we’ll be installing the Mesh handler for the OpenAPI spec:
$ yarn add graphql @graphql-mesh/openapi
To see a full list of the supported API specs, consult the GraphQL-mesh documentation.
Now you can run GraphQL. Type the following command:
$ yarn graphql-mesh serve
This serves an instance of GraphQL following the schema you’ve provided to http://localhost:4000/, so you can test your code and make sure everything’s working as it should be.
Now let’s see an example of GraphQL Mesh in action to give you an idea of how you can integrate it into your development workflow. It’ll also help you visualize how GraphQL Mesh can make consolidating data from multiple API sources much easier and more intuitive than other languages.
To illustrate some of these concepts, we’re going to build a simple app that consolidates data from two different APIs and merges them together. We’re gathering data from a weather API and an API of geographic data.
For the sake of good housekeeping, let’s create a new directory for our project. We’ve named ours locationweather
. Navigate to this folder using Terminal.
Now we’ll start by re-installing our libraries and gathering the permissions we’ll need. Once you’re in your programming director, type:
npm install yarn --global yarn add graphql @graphql-mesh/runtime @graphql-mesh/cli yarn add apollo-server yarn add @graphql-mesh/openapi
This installs the libraries that will be called inside of our GraphQL function and makes them available globally.
Now open an instance of your preferred text editor for programming.
We’re using Notepad++, since it lets you save files in whatever file format you prefer.
Let’s start by making the GraphQL schema, which makes up the bulk of what your GraphQL function does. In the root directory of your project folder, create a file called .meshrc.yaml
using your text editor and save it. Then input the following:
sources: - name: Cities handler: openapi: source: https://api.apis.guru/v2/specs/mashape.com/geodb/1.0.0/swagger.json operationHeaders: 'X-RapidAPI-Key': f93d3b393dmsh13fea7cb6981b2ep1dba0ajsn654ffeb48c26 - name: Weather context: apiKey: 971a693de7ff47a89127664547988be5 handler: openapi: source: https://api.apis.guru/v2/specs/weatherbit.io/2.0.0/swagger.json transforms: - extend: | extend type PopulatedPlaceSummary { dailyForecast: [Forecast] todayForecast: Forecast } - cache: # Geo data doesn't change frequntly, so we can cache it forever - field: Query.* # Forecast data might change, so we can cache it for 1 hour only - field: PopulatedPlaceSummary.dailyForecast invalidate: ttl: 3600 - field: PopulatedPlaceSummary.todayForecast invalidate: ttl: 3600 require: - ts-node/register/transpile-only additionalResolvers: - ./src/mesh/additional-resolvers.ts
You can see this function is calling the APIs we’re working with for this project. It should give you an idea of how these principles can be applied to practically any API or data source you may want to work with.
Next, you’re going to create package.json
, which makes up much of the rest of this simple app. Create a blank file and put the following code into the body:
{ "name": "typescript-location-weather-example", "version": "0.0.20", "license": "MIT", "private": true, "scripts": { "predev": "yarn mesh:ts", "dev": "ts-node-dev src/index.ts", "prestart": "yarn mesh:ts", "start": "ts-node src/index.ts", "premesh:serve": "yarn mesh:ts", "mesh:serve": "graphql-mesh serve", "mesh:ts": "graphql-mesh typescript --output ./src/mesh/__generated__/types.ts" }, "devDependencies": { "@types/node": "13.9.0", "ts-node": "8.8.2", "ts-node-dev": "1.0.0-pre.44", "typescript": "3.8.3" }, "dependencies": { "@graphql-mesh/cli": "0.0.20", "@graphql-mesh/openapi": "0.0.20", "@graphql-mesh/runtime": "0.0.20", "@graphql-mesh/transform-cache": "0.0.20", "@graphql-mesh/transform-extend": "0.0.20", "apollo-server": "2.11.0", "graphql": "15.0.0" } }
You can see that most of the variables we’ll be using are defined in package.json
. This is another of GraphQL’s greatest strengths — its ability to be hard-typed. Things are much more settled and fixed and, thus, less likely to break using GraphQL’s JSON strings.
The last file of substance in our root directory is tsconfig.ts
. Create the file and insert these few short lines:
{ "compilerOptions": { "target": "es2015", "module": "commonjs", "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ "lib": [ "esnext" ], "sourceMap": true /* Generates corresponding '.map' file. */, }, "include": ["src"], "exclude": ["node_modules"] }
Now there’s just a tiny bit more housekeeping to do incase anyone uses this app after you. We’ll make a readme file, README.md
:
## Location-Weather Example
This example takes two API sources based on Openapi 3 and Swagger, and links between them.
It allows you to query for cities and locations, and include fields for the weather in that found place.
Finally, we’ll create a file responsible for some additional routing,called .gitingore
with no file extension.
__generated__ src/__generated__
We’re almost done! There’s just the tiniest bit of additional formatting we’ll want to incorporate. To do so, start off by creating a sub-folder called SRC
. Then make a file called index.ts
.
Insert the following code:
import { ApolloServer } from 'apollo-server'; import { getMesh, findAndParseConfig } from '@graphql-mesh/runtime'; async function main() { const meshConfig = await findAndParseConfig(); const { schema, contextBuilder } = await getMesh(meshConfig); const server = new ApolloServer({ schema, context: contextBuilder, }); server.listen().then(({ url }) => { console.log(`🚀 Server ready at ${url}`); }); } main().catch(err => console.error(err));
You can see that index.ts
imports the functions we installed earlier, like apollo-server and, of course, GraphQL Mesh, and makes them available to the rest of the functions.
Create one more additional sub-folder in the src
directory and call it mesh
. You’re going to make one final file, in that folder, called additional-resolvers.ts
:
import { Resolvers } from './__generated__/types'; export const resolvers: Resolvers = { PopulatedPlaceSummary: { dailyForecast: async (placeSummary, _, { Weather }) => { const forecast = await Weather.api.getForecastDailyLatLatLonLon({ lat: placeSummary.latitude!, lon: placeSummary.longitude!, key: Weather.config.apiKey, }); return forecast.data!; }, todayForecast: async (placeSummary, _, { Weather }) => { const forecast = await Weather.api.getForecastDailyLatLatLonLon({ lat: placeSummary.latitude!, lon: placeSummary.longitude!, key: Weather.config.apiKey, }); return forecast.data![0]!; }, }, };
That’s the last of the code! Now you can go to the command line and run:
yarn graphql-mesh serve
This will serve your app to http://localhost:4000, running on an instance of GraphQL, where you can perform your queries and mutations.
If you’d like to try out GraphQL Mesh without messing with any code, the entire project is available on codesandbox, including the code, so you can see GraphQL Mesh in action for yourself and get a sense of how you might integrate this clever translator into your existing workflow.
GraphQL Mesh is a dream come true for frontend developers and end users alike.
From the client’s perspective, they don’t have to know as much about the API structure to do what they’re trying to do. Instead, they just need to know what they’re querying for and GraphQL Mesh delivers.
From the programmer’s perspective, GraphQL Mesh makes code exponentially more robust and flexible. You won’t have to worry about reconfiguring your API every time you change your data. No more routing endless endpoints or constantly coding complex databases.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.
LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. Start monitoring for free.Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowReact Native’s New Architecture offers significant performance advantages. In this article, you’ll explore synchronous and asynchronous rendering in React Native through practical use cases.
Build scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.