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: [] });
}