@muellerbbm-vas/grivet v0.0.9
Grivet
A JSON:API client library written in Typescript with emphasis on RESTful traversal of resources according to HATEOAS principles.
Features
- Transparent access to included resources (in compound documents) as well as linked resources (fetched from a server)
Promise-based access to resources allowingasync/awaitstyle programming- Adaptable to various HTTP client implementations
- Focus on traversing JSON:API resources without knowing specific URLs, as recommended by REST/HATEOAS
- Support for sparse fieldsets
- Uses memoization to avoid repeated network requests and repeated traversals of the document structure
- No dependencies (apart from
jestfor testing) - Implemented against the JSON:API 1.0 specification.
Non-Features
Grivet does not aim to be an ORM. It does not provide methods to manage resources on a server (e.g. deleting or updating resources).
Installation
npm i @muellerbbm-vas/grivetBasic Usage
To give an idea of what using Grivet looks like, the code snippet below shows how to traverse from an API entry point to the author of a specific article:
import { JsonApi } from '@muellerbbm-vas/grivet';
const apiEntryPointDoc = await JsonApi.Document.fromURL(new URL('http://example.com/api/'), context);
const articles = await apiEntryPoint.resource.relatedResources['articles'];
const author = await articles[0].relatedResource['author'];
const name = author.attributes['name'];In the first line, a JSON:API document is constructed from a given URL and a Context object
(see the documentation on contexts for more details). The Promise returned by the fromURL function is awaited to obtain the Document (corresponding to the JSON:API top level document). The raw JSON:API document fetched from the server might look something like this:
GET http://example.com/api HTTP/1.1
Accept: application/vnd.api+json
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": {
"type": "entrypoints",
"id": "1",
"relationships": {
"articles": {
"links": {
"related": "http://example.com/articles"
}
},
"people": {
"links": {
"related": "http://example.com/people"
}
}
}
}
}The entry point document contains a primary resource with a relationship named "articles" pointing to the articles resources.
The second line of our short example gets the primary entry point resource and then directly awaits the relatedResources property to fetch the
articles resources as an array of Resource objects (corresponding to JSON:API resource objects).
As recommended by HATEOAS principles, we do not need to know the URL of the articles resource in advance, we just follow the provided relationship.
Let's assume the server responds with the following compound JSON:API document:
GET http://example.com/articles HTTP/1.1
Accept: application/vnd.api+json
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"data": [
{
"type": "articles",
"id": "1",
"relationships": {
"author": {
"data": { "type": "people", "id": "9" }
}
}
}
],
"included": [
{
"type": "people",
"id": "9",
"attributes": {
"name": "example name"
}
}
]
}The article resource contains a relationship to its author, which in this case is included in the document.
The third line of our small example uses the relatedResource property to obtain the author resource linked in the first article.
We do not have to know whether the relationship links to an included resource or whether it needs to be fetched from a server.
We just await the relatedResource property.
The attributes of the author resource can then simply be obtained using its attributes property.
Guides
- Implementing the
Contextinterface - Using Sparse Fieldsets
- Experimental: constructing a document for POSTing to a server
Examples
Listing all relationships of a resource
The relationships property of a Resource contains all relationships as a map from relationship name to Relationship object. This map can be iterated to find all relationships:
for (const relationshipName in articleResource.relationships) {
const relationship = articleResource.relationships[relationshipName];
// … do something with relationship
}More examples
See test/tests.spec.ts for more examples of how to use this library.
Reference documentation
Have a look at the library reference for more details.
TODO
License
Copyright © 2019-2022 Müller-BBM VibroAkustik Systeme GmbH
Licensed under the MIT license