contiamo-rest-client
v1.1.5
Published
Simple RESTful JS client to interact with nested resources in a given backend.
Downloads
10
Keywords
Readme
Contiamo REST Client
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:
GET https://api.myapp.com/tenants/123/bundles
The above URL signals two things:
- There is a
collection
ofresource
s available at/tenants
. - There is a more specific
tenant
(#123) that we want to retrievebundle
s 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
Consider:
import {
Collection,
Listable,
Fetchable,
Destroyable,
Resource
} 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
Consider:
import { Client } from "contiamo-rest-client"
import blueprint from "./api"
const myClient = new Client(blueprint, {
apiBase: 'https://whatever.rest/',
})
The client then exposes an API as so:
/**
* Keeping the URL in mind,
* GET https://api.myapp.com/tenants/123/bundles
*/
const getBundles = async () => await myClient
.children('tenants')
.build('123')
.children('bundles')
.list()
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.
Privileges
Below is a brief overview of the various privileges (.list()
, .fetch()
, etc.) available to Collections
and to Resource
s.
Collection
Privileges
Listable(Collection)
This privilege lets a collection (or list) be retrieved. (GET
)
Usage: Collection.list()
const listChildren = async () => await Client.children('myListableCollection').list()
Creatable(Collection)
This privilege lets a collection (or list) be created. (POST
)
Usage: Collection.create()
const createCollection = async () => await Client.children('myListableCollection').create()
Resource
Privileges
Fetchable(Resource)
This privilege lets a single resource be retrieved. (GET
)
Usage: Resource.fetch()
const listChildren = async () => await Client.children('myListableCollection').build('123').fetch()
Modifiable(Resource)
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'
}
})
Destroyable(Resource)
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 fetch
ing 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.
Contributing
git clone [email protected]:Contiamo/rest-client.git
yarn install
code .
(oratom .
orslime .
or whatever dude)
Look up and create issues, make PRs, spread the love. ❤️