Simple RESTful JS client to interact with nested resources in a given backend.

Usage no npm install needed!

<script type="module">
  import contiamoRestClient from '';


Contiamo REST Client

Build Status

This REST client attempts to communicate with a backend API, interacting in a declarative way.

Getting Started

First, you'll want to add the contiamo-rest-client to your project like so:

npm install contiamo-rest-client, alternatively yarn add contiamo-rest-client if you're into yarn.

Then, your code needs a couple of building blocks:

Block 1 - an API blueprint

Consider the following REST endpoint:


The above URL signals two things:

  1. There is a collection of resources available at /tenants.
  2. There is a more specific tenant (#123) that we want to retrieve bundles for.

Expressed as a blueprint that this client understands, this would look like:

import { TenantCollection, BundleCollection } from "./collections"

export default {
    key: 'tenants',
    collection: TenantCollection,
    path: 'tenants',
    children: [
            key: 'bundles',
            collection: BundleCollection,
            path: 'bundles',

From the above snippet, we see that the BundlesCollection is a child of TenantsCollection, similar to our URL structure.

But what is TenantsCollection?

Block 2 - Collections and Resources


import { 
} from "contiamo-rest-client"

export class TenantsCollection extends Listable(Collection) {
    constructor() {
        this.resource = Fetchable(Destroyable(Resource))

From the above snippet, we see the proper intended usage of this client. The client exposes a Collection and a Resource onto which certain privileges can be applied: Fetchable, Listable, Destroyable, Editable, Retrievable, etc. These privileges, under the hood, really just map to their respective HTTP verbs.

The API blueprint composes these collections together.

Putting It All Together: Instantiating the Client


import { Client } from "contiamo-rest-client"
import blueprint from "./api"

const myClient = new Client(blueprint, {
    apiBase: '',

The client then exposes an API as so:

 * Keeping the URL in mind,
 * GET

const getBundles = async () => await myClient

This would fetch a list of bundles for tenant 123. To fetch a specific bundle resource, one could instead write .children('bundles').build('456').fetch().

The API of this client is self-documenting when using TypeScript and an autocomplete feature like IntelliSense.


Below is a brief overview of the various privileges (.list(), .fetch(), etc.) available to Collections and to Resources.

Collection Privileges


This privilege lets a collection (or list) be retrieved. (GET)

Usage: Collection.list()

const listChildren = async () => await Client.children('myListableCollection').list()


This privilege lets a collection (or list) be created. (POST)

Usage: Collection.create()

const createCollection = async () => await Client.children('myListableCollection').create()

Resource Privileges


This privilege lets a single resource be retrieved. (GET)

Usage: Resource.fetch()

const listChildren = async () => await Client.children('myListableCollection').build('123').fetch()


This privilege lets a single resource be modified. (PUT)

Usage: Resource.modify()

const listChildren = async () => await Client.children('myListableCollection').build('456').modify({ 
    data: {
        updatedData: 'hello' 


This privilege lets a single resource be deleted. (DELETE)

Usage: Resource.destroy()

const listChildren = async () => await Client.children('myListableCollection').build('789').destroy()

How It Works

Basically, the Client at the top of the .children().build().children().build().doSomething() chain is the single point of contact with a backend API. This is where the fetching happens. Everything else is just syntactic sugar that consults the blueprint in order to construct a path to query. When request is called on a Resource or a Collection, this method bubbles up to the top-level request method on Client, that does the actual server communication.


  1. git clone
  2. yarn install
  3. code . (or atom . or slime . or whatever dude)

Look up and create issues, make PRs, spread the love. ❤️