DEV Community

Cover image for Announcing the Wundergraph Hub, like npm, but for APIs
Stefan  🚀
Stefan 🚀

Posted on • Edited on • Originally published at wundergraph.com

Announcing the Wundergraph Hub, like npm, but for APIs

Do you remember how we shared applications before Docker existed? Applications were not as portable as they are today. You had to install all the required packages, manually or automated, but it was nowhere near as easy as docker run or docker build.

Docker, or better yet OCI (Open Container Image), completely changed the way the bundle applications and distribute them. Today, you can pull an image from a Docker registry and run it on your local machine or in the cloud.

Similarly, could you imagine a world without package managers like npm, Composer, or Maven? There was a time when JavaScript libraries like jQuery had to be included directly in the HTML from a CDN. The way we develop software today heavily relies on package managers.

What both of these categories of tools have in common is that they fundamentally changed the way we develop software. They enabled new workflows and made it easier for developers to collaborate and share code.

Docker / OCI for example paved the way for kubernetes, standardizing the way how applications can be deployed in cloud native environments.

So what's the point of mentioning these two when we actually want to talk about APIs? Well, I believe that we're still in the stone age when it comes to APIs.

While the API community developed tools like API Gateways and Developer Portals to secure and distribute APIs, they completely forgot to think about the developer experience of API developers and their consumers.

What happens when you visit a developer portal and decide, you'd like to use the API in your project? You download the SDK or use the Swagger / OpenAPI specification and start a manual integration process. You cannot just run npm install and hope that everything works out of the box.

The typical project doesn't just talk to a single database in isolation. You will probably have to integrate with multiple APIs from different teams or even third parties. Microservice architectures require a lot of integration work. Additionally, there are many powerful SaaS providers that offer APIs, e.g. for sending emails, managing user accounts, etc.

When it comes to integrating all these services, developers have to go through a lot of manual work. Wrapping SDKs, building backends for frontends and handling authentication are just a few of the problems to tackle. Most of the time, this manual integration work is not shared because it's proprietary closed source code that cannot be shared publicly. This means that API consumers do the same or similar work over and over again, wasting time and money.

Our goal is to change this! We want to make API integration as simple as npm install. Our goal is to make APIs as portable as Docker containers, allowing API developers and their consumers to collaborate at a whole new level.

Manually integrating APIs is like importing jQuery from a CDN, let's get rid of that!

The solution: How to make APIs easily portable

Similarly to Docker, we need a common language to make APIs portable. Additionally, we need a runtime to run our API integrations on.

Once we have these two, we need a place to store our API integrations so that API developers can "publish" their APIs and consumers can "pull" them into their projects, similar to Docker or npm.

GraphQL: The common language for API integrations

For the language, we've decided to use GraphQL. By combining all APIs into a single GraphQL schema, we're able to "query" data from multiple APIs at once.

Additionally, GraphQL comes with a powerful type system, making it very easy to generate e.g. TypeScript interfaces for your integrations.

WunderGraph: The runtime for API integrations

What we've done for the last year is to build the runtime for API integrations. WunderGraph makes it easy to combine APIs from different services into a single GraphQL schema. Our Runtime / Engine is capable of combining them into a common format, allowing you to execute GraphQL Operations against almost any service.

So far, we're supporting the following Backends:

REST (OpenAPI / Swagger)
GraphQL
Apollo Federation
PostgreSQL
MySQL
SQLite
SQL Server
Enter fullscreen mode Exit fullscreen mode

You can "introspect" any of those and turn them into the "portable" WunderGraph format with a single command.

In addition to the above backends, we also support the following Frontends:

REST(-ish) API
Postman Collections
Generated SDKs: 
    TypeScript
    React
    React Native
Enter fullscreen mode Exit fullscreen mode

When we talk about "frontends" we're talking about how to consume the API integrations. WunderGraph doesn't just combine your APIs into a GraphQL Schema and calls it a day. We go one step further, generating complete ready-to-use SDKs for your APIs that not just let you call your APIs, but also handle authentication and authorization, caching, security and more.

The WunderGraph Hub: A place to store and share API integrations

The last component of our solution is the WunderGraph Hub. It's a place where you can store and share API integrations. Similarly to the Docker Hub or npm, you can publish your API descriptions and share them with the community.

You could share them publicly with everyone or limit access to just a group of people, e.g. only those of your own organization.

With the three components, the common language, the Runtime and the Hub, let's have a look at the flow of integrating APIs using WunderGraph and the Hub.

How does it work?

Sharing an API using the WunderGraph Hub

The first step is to introspect the API you want to share and translate it into the portable WunderGraph format. This can be done using the TypeScript SDK of WunderGraph. Here's an example:

// first, introspect an API
const countries = introspect.graphql({
    url: "https://countries.trevorblades.com/",
});

// then, prepare it for publishing it to the Hub
configurePublishWunderGraphAPI({
    organization: "wundergraph",
    apiName: "countries",
    title: "Trevor's Countries",
    markdownDescriptionFile: "countries.md",
    public: true,
    keywords: ["countries","trevor","trevorblades"],
    apis: [
        countries,
    ],
});
Enter fullscreen mode Exit fullscreen mode

The SDK lets you introspect one or more APIs which you can then combine and publish. Similarly to how npm works, you publish the API to an organization and can use various methods to describe it.

Once you're ready to publish, run the following command:

$ wundergraph publish generated/wundergraph.countries.api.json
Enter fullscreen mode Exit fullscreen mode

Integrating an API published on the Hub#

Now let's talk about the flow of integrating APIs using WunderGraph.

First, let's init a new project.

$ wundergraph init#
$ cd .wundergraph
$ yarn
Enter fullscreen mode Exit fullscreen mode

Then let's add two APIs to our workspace.

$ wunderctl integrations add wundergraph/countries wundergraph/spacex
Enter fullscreen mode Exit fullscreen mode

The added API dependencies are automatically downloaded and installed. All API dependencies of a project are stored in the wundergraph.manifest.json file.

{
  "dependencies": [
    "wundergraph/spacex",
    "wundergraph/countries"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Once we've added the APIs to our workspace, we can add them to our WunderGraph API using the WunderGraph SDK.

import {
    Application,
    configureWunderGraphApplication,
    cors,
    templates
} from "@wundergraph/sdk";
import wunderGraphHooks from "./wundergraph.hooks";
import operations from "./wundergraph.operations";
import {integrations} from "./generated/wundergraph.integrations";

const spacex = integrations.wundergraph.spacex({
    apiNamespace: "spacex",
});

const countries = integrations.wundergraph.countries({
    apiNamespace: "countries",
});

const myApplication = new Application({
    name: "app",
    apis: [
        spacex,
        countries,
    ],
});
Enter fullscreen mode Exit fullscreen mode

As you can see, we're instantiating both APIs from the generated "integrations" file. There's one little detail that might spark your attention, the apiNamespace parameter.

WunderGraph combines all your APIs into a single GraphQL Schema. If you combine APIs from different teams or vendors into the same GraphQL Schema, you're very likely to run into naming collisions and your Schema will be broken. By putting different APIs into their own namespace, we're able to avoid these problems without manual configuration.

As a final step, we have to define an operation to interact with our newly created API.

query DragonsAndContries {
    dragons: spacex_dragons {
        name
        active
    }
    countries: countries_countries {
        code
        name
        capital
    }
}
Enter fullscreen mode Exit fullscreen mode

This Query retrieves data from both the SpaceX and Countries APIs. You can also see how the root level fields of both APIs are prefixed with the API namespace.

You're now ready to start your WunderGraph application and start using it.

# cd into the .wundergraph directory and run:
$ wunderctl up --debug
Enter fullscreen mode Exit fullscreen mode

And finally, let's query it!

$ curl http://localhost:9991/api/main/operations/DragonsAndContries
Enter fullscreen mode Exit fullscreen mode

In this example, we're simply using curl to query the generated REST(-ish) API, but you could also go more advanced and use a generated TypeScript client, the generated Postman Collection, etc...

Summary

We've introspected a GraphQL API using the SDK, prepared it for publishing and then pushed it to the hub.

Then, as an API consumer, we've added two APIs to our project and instantiated them with an api namespace. Finally, we've defined an Operation and interacted with our newly created API integration using curl.

This might look like a simple example but I hope it's clear how much time we're able to save.

How does the world look like without using this flow?

As we've said earlier, we think that API integrations are still in the stone age, so let's contrast the WunderGraph flow with how developers would save the same problem without WunderGraph.

First, you have to decide on a technology, language and framework to build your REST API
Then, add a new endpoint to your API
Use a tool like graphql-code-generator to generate a typesafe API client for both APIs
Use the generated client to query both APIs and implement the REST Endpoint
Define a JSON Schema for the REST Endpoint
Add an authentication and authorization layer to your REST Endpoint (this is batteries included in WunderGraph)
Add a caching middleware (this is batteries included in WunderGraph)
Use curl to query the REST Endpoint
Enter fullscreen mode Exit fullscreen mode

We could easily make the list a lot longer because WunderGraph does way more than just integrating APIs. Have a look at our Features, our suite of tools helps you solve all problems around APIs, from authentication to authorization, role based access control, mocking, JSON Schema validation, automatic ETags, S3 file uploads and many more.

Additionally, imagine what happens if you have to add another API or one of the APIs needs to be updated. With WunderGraph and the Hub, it's a matter of minutes and mostly automatic. You shouldn't really waste your time for such a boring task.

Announcing the WunderGraph Hub closed Beta

WunderGraph, the Runtime / Engine is very stable and ready for production. Together with our community of WunderGraph fans, we've been able to mature it over the last few months.

It's now time to move forward towards the final step before we want to release our framework to the public, Open Source and with no restrictions.

To make this final step easier, we need feedback from you, the community!

We're asking you to join our closed beta and help us to optimize the Developer Experience of both the WunderGraph Framework and the Hub.

If you're interested, please have a look at https://hub.wundergraph.com and sign up for the private beta. Additionally, you can also join our Discord and ask to join the Beta there.

We'd love to hear from you if you think the Hub and our Framework could help you to improve your experience of working with APIs.

The Future

Our plan is to release our Open Source Framework in January 2022. Our long term goal is to be able to connect more backends and integrate with more frontend technologies.

On the backend side, we'd like to add support for SOAP, OData, gRPC and MongoDB. On the frontend side, we're looking at supporting Vue, Svelte, Angular, iOS, Android, Flutter, Java, Go, Python, Ruby, PHP, Typescript, Swift, Kotlin, C#.

Our vision is to become a meta-framework to solve all problems around APIs while being both backend and frontend agnostic. You should be able to use any backend or frontend technology, we're handling the heavy lifting of API integrations, security and more.

Top comments (0)