Introducing RestQL.js

Ariel Díaz
Jan 22, 2018 · 4 min read

RESTful API Resolver for Nested-Linked Resources | 🕸 🕷

Introduction

For almost the past two decades, RESTful APIs have been the go-to solution when it comes to developing distributed applications across the Internet.

Nonetheless, the industry has not yet defined formal documentation for implementing patterns on different endpoints.

This leading to inconsistency between two different RESTful APIs, which is totally fine since they both probably target custom applications; e.g.:

  • /productWithTaxes/:id/
  • /product/:id/?withTaxes=true

Normalized Implementations

In case of needing to provide a more generic RESTful API, endpoints should be as flat as possible, so that consumers can use them at their will.

Pokéapi has made an incredible job by exposing flatten endpoints that reflect its internal data structure.

Before we dive into a more technical debate, let’s see how it looks in practice such implementation from the mentioned page.

Sample Response for https://pokeapi.co/api/v2/pokemon/1/

As seen on the gist above, properties that solely belong to the requested resource are present directly on the response; e.g.:

  • name
  • weight

While others considered as foreign properties are referenced to external resources, in this case through the url property.

Problem

When it comes to consuming this RESTful API, the first issue we face as developers is the lack of useful information on each response.

At first glance, it seems like almost every response contains further references to yet another request, which can be intimidating if not handled properly.

Let’s walk together on a simple, yet complex data challenge:

As a trainer, I want to see a dashboard with my Pokémon’s statistics so that I can better understand its strengths and weaknesses by nature.

By looking at the previous gist, it’s pretty clear that we get the stats property, which is an array of objects containing our desired data.

And sooner than later, we quickly realize that we’ll require additional information in order to fulfill our data needs.

Sample Response for https://pokeapi.co/api/v2/stat/6/

Although we’re getting closer, we’re not there yet, the new response describes how a status is affected by different natures.

And yet again, we face the same issue of requiring additional information…

Proposed Solution

Rather than going over a naive non-elegant example, let’s simply write down the steps required to get the data we need:

  1. Fetch the initial resource: https://pokeapi.co/api/v2/pokemon/1/
  2. Loop over the stats[].stat.url properties, and fetch them as well.
  3. Loop over the affecting_natures.increase[].url properties.
  4. Loop over the affecting_natures.decrease[].url properties.
  5. For steps 3 and 4, fetch the resources while keeping all in sync.

Although this approach would work for our trivial challenge, the same won’t scale when dealing with different structures among RESTful APIs.

Hence RestQL.js: a simple yet robust library which allows us to solve this and other more complex data requirements scenarios.

As its name and description imply, its sole purpose is to resolve various calls within a RESTful API, while abstracting the logic away from us.

Let’s go over a simple implementation that allows us to get the same exact data we need from our previous challenge.

Sample Usage

As seen on the playground above, the interface empowers developers to focus on what they need, rather than how it gets it using the resolver.

The same is the core of the library, which enables recursive capabilities when specifying nested-linked resources.

You can go as depth as you need to, without worrying about performance or wasting the users’ bandwidth on high-latency networks.

Since the library itself will resolve them asynchronously, while at the same time storing the responses on a flatten local cache for further usage.

In the end, you will receive a huge object containing the merged responses according to our resolver definition.

Where, in this example, each url property representing a resource will be replaced with its corresponding response.

Hint #1: in case of the target RESTful API requiring authentication, you can optionally pass an options parameter, which is based on axios.

Hint #2: from here, we could easily implement a custom schema in order to flatten the huge object with the use of libraries like normalizr.

Conclusion

Even though industry leaders have started adopting new technologies, such as GraphQL, the lifespan for RESTful APIs is still long.

This is an attempt from me to ease our workflow when dealing with this kind of implementations.

Since this is an open-source project, you’re more than welcome to contribute!

https://github.com/adjesusds/restql/


If you enjoyed this article and feel like it’s worth a clap, please do so. 👏

Follow me on social media as: @adjesusds

And feel free to reach out, in case you’d ever want to talk…

Take 🍰, Folks! 🌮 🐴 💨

Ariel Díaz

Written by

/^(?:develop|speedcub|runn)er$/

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade