@muellerbbm-vas/grivet
TypeScript icon, indicating that this package has built-in type declarations

0.0.9 • Public • Published

Grivet

Node.js CI NPM

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 allowing async/await style 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 jest for 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/grivet

Basic 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

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

Package Sidebar

Install

npm i @muellerbbm-vas/grivet

Weekly Downloads

184

Version

0.0.9

License

MIT

Unpacked Size

258 kB

Total Files

43

Last publish

Collaborators

  • teksidot
  • danielmenzel