Skip to content

Instantly share code, notes, and snippets.

@tchak
Last active June 24, 2019 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tchak/862cfea0995bb5c5b90fd712b076e00e to your computer and use it in GitHub Desktop.
Save tchak/862cfea0995bb5c5b90fd712b076e00e to your computer and use it in GitHub Desktop.
Orbit jsonapi Client

Is it possible to use Orbit.js as a simple fetching client with a json:api server? The answer is yes, with certain caveats. First one is you still need to write a schema.

import { Schema } from '@orbit/data';
import JSONAPISource from '@orbit/jsonapi’;

const schema = new Schema({
  models: {
    article: {
      attributes: {
        title: { type: 'string' }
      },
      relationships: {
        author: {
          type: 'hasOne',
          model: 'profile'
        }
      }
    },
    profile: {
      attributes: {
        username: { type: 'string' }
      }
    }
  }
});

const client = new JSONAPISource({
  schema,
  host: 'https://api.myservice.com'
});

// Lets query our API. That was easy!
const article = await client.query(q => q.findRecord({ type: 'article', id: '123' }));

// Now I want to fetch the author of the article along side the article.
const article = await client.query(q => q.findRecord({ type: 'article', id: '123' }), {
  include: 'author'
});
// This will issue expected query to the server, but you will stil get back only the article.
// What happened? The sideloaded data was emited as a set of transforms.

// You can use `pull` interface instead. It will return a full set of fetched records,
// but as a set of transforms.
const transforms = await client.pull(q => q.findRecord({ type: 'article', id: '123' }), {
  include: 'author'
});

// All transforms returned from `pull` will contain a set of `RecordUpdateOperation`.
// It is possible to write a function to get a json:api document from transforms.
// Caveat here is thet you mightloos ordering in case of `findManyRecords`.
// Also If you have same type records in relationships, this will not work.
function transformsToJSONAPIDocument(transforms, type, many = false) {
  return transforms.flatMap(({ operations }) => operations).reduce((document, operation) => {
    if (operation.record.type === type) {
      if (many) {
        document.data.push(operation.record);
      } else {
        document.data = operation.record;
      }
    } else {
      document.included.push(operation.record);
    }
    return document;
  }, { data: many ? [] : null, included: [] });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment