Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/krainboltgreene/hsdk.js

A HATEOAS HTTP client that generates SDKs based on a specific endpoint
https://github.com/krainboltgreene/hsdk.js

hateoas jsonapi mediatype sdk

Last synced: 9 days ago
JSON representation

A HATEOAS HTTP client that generates SDKs based on a specific endpoint

Awesome Lists containing this project

README

        

# hsdk

hsdk stands for HATEOAS Software Development Kit. This library reads from a specified 'application metadata' endpoint and generates an HTTP HATEOAS API client.

![Version][BADGE_VERSION]
![Tests][BADGE_TRAVIS]
![Stability][BADGE_STABILITY]

Example at play: https://esnextb.in/?gist=1ddc4e3e62196c8b9542b87a6141dff4

## using

First you need to define your core sdk and in this example we'll our jsonapi.org specification-compliant endpoint:

``` javascript
import hsdk from "hsdk"
import axios from "axios"

const sdk = hsdk({
home: {
url: "https://hsdkjs.getsandbox.com/v1/resources",
headers: {
Accept: "application/vnd.api+json",
},
},
// You tell us how to make the request
http: ({url, method, payload}) => axios({
method,
url,
data: payload,
responseType: "JSON",
}),
// You tell us how to get to the JSON:API data
receive: (body) => body.data,
})
```

The `sdk` constant above is a `Promise` based on a request/response to/from the home resource.

Now we can start making requests to our api, discovered 🌟magically🌟:

``` javascript
sdk
.then((client) => client.accounts.v1.list())
.then((response) => console.log({message: "List", payload: response.data}))
```

That will `log` a list of accounts.

``` javascript
sdk
.then((client) => client.accounts.v1.show({id: "1"}))
.then((response) => console.log({message: "Show", payload: response.data}))
```

This will `log` a single account, with the `id` of `1`

``` javascript
sdk
.then((client) => {
return client.accounts.v1.update({
id: "1",
payload: {
data: {
id: "1",
type: "accounts",
attributes: {
age: 29
}
}
}
})
})
.then((response) => console.log({message: "Update", payload: response.data}))
```

In `POST`, `PATCH`, or `PUT` requests (mutations) `hsdk` expects a `payload` value that it uses in the body. This `update` request will update the age of `accounts/1` to `29`.

hsdk doesn't care what kind of API you have, only that it is discoverable via `jsonapi-home`.

## jsonapi-home

Much like [json-home](https://mnot.github.io/I-D/json-home/), a fantastic spec by @mnot, jsonapi-home is an attempt to allow clients to build themselves.

Using the example above, we need a HTTP server running at `http://hsdkjs.getsandbox.com` that responds to `GET /v1/resources` requests.

Here is a sample CURL-based request (an example of what hsdk does under the hood):

``` bash
curl -X "GET" "http://hsdkjs.getsandbox.com/v1/resources" \
-H "Accept: application/vnd.api+json"
```

Each resource MUST have the following properties:

- intent: The human name for this result, example: `list`, `show`, `create`, `destroy`, `update`
- namespace: The groupings this resource is under, can be anything
- version: The version of the endpoint, if no version you SHOULD use `latest`
- description: A short description for the resource
- method: The HTTP verb used
- href: A RFC 6570 URL template that the client can use directly
- mediatype: The preferred mediatype for this endpoint

That response will look like this:

``` http
HTTP/1.1 200 OK
Accept: application/vnd.api+json
Content-Type: application/vnd.api+json
Date: Mon, 28 Nov 2016 19:50:32 GMT

{
"links": {
"self": "https://hsdkjs.getsandbox.com/v1/resources",
"next": "https://hsdkjs.getsandbox.com/v1/resources?page[offset]=2",
"last": "https://hsdkjs.getsandbox.com/v1/resources?page[offset]=10"
},
"data": [
{
"id": "accounts-v1-list",
"type": "resources",
"attributes": {
"intent": "list",
"namespace": "accounts",
"version": "v1",
"description": "List accounts.",
"method": "GET",
"href": "https://hsdkjs.getsandbox.com/v1/accounts",

"mediatype": "application/vnd.api+json"
},
"links": {
"self": "https://hsdkjs.getsandbox.com/v1/resources/accounts-v1-list"
}
},
{
"id": "accounts-v1-show",
"type": "resources",
"attributes": {
"intent": "show",
"namespace": "accounts",
"version": "v1",
"description": "Show an individual account.",
"method": "GET",
"href": "https://hsdkjs.getsandbox.com/v1/accounts/{id}",
"allowed": [
["fields"]
],
"mediatype": "application/vnd.api+json"
},
"links": {
"self": "https://hsdkjs.getsandbox.com/v1/resources/accounts-v1-show"
}
},
{
"id": "accounts-v1-update",
"type": "resources",
"attributes": {
"intent": "update",
"namespace": "accounts",
"version": "v1",
"description": "Update an individual account.",
"method": "PATCH",
"href": "https://hsdkjs.getsandbox.com/v1/accounts/{id}",
"mediatype": "application/vnd.api+json"
},
"links": {
"self": "https://hsdkjs.getsandbox.com/v1/resources/accounts-v1-update"
}
}
]
}
```

[BADGE_TRAVIS]: https://img.shields.io/travis/krainboltgreene/hsdk.js.svg?maxAge=2592000&style=flat-square
[BADGE_VERSION]: https://img.shields.io/npm/v/hsdk.svg?maxAge=2592000&style=flat-square
[BADGE_STABILITY]: https://img.shields.io/badge/stability-strong-green.svg?maxAge=2592000&style=flat-square