kitsu-core
Version:
Simple, lightweight & framework agnostic JSON:API (de)serialsation components
81 lines (78 loc) • 2.37 kB
JavaScript
import { deattribute } from './deattribute.mjs';
import { linkRelationships } from './linkRelationships.mjs';
import './filterIncludes.mjs';
import './error.mjs';
function hoistData(response) {
const seen = new WeakMap();
const hasOwn = Object.prototype.hasOwnProperty;
function hoist(object) {
if (object && typeof object === 'object') {
if (seen.has(object)) {
return seen.get(object);
}
let out;
if (Array.isArray(object)) {
out = [];
seen.set(object, out);
let i = 0;
for (const item of object) {
out[i] = hoist(item);
i++;
}
return out;
}
let onlyData = false;
for (const key in object) {
if (!hasOwn.call(object, key)) continue;
if (key === 'data' && !onlyData) {
onlyData = true;
} else {
onlyData = false;
break;
}
}
if (onlyData) {
return hoist(object.data);
}
out = {};
seen.set(object, out);
for (const key in object) {
if (hasOwn.call(object, key)) {
out[key] = hoist(object[key]);
}
}
return out;
}
return object;
}
return hoist(response);
}
function deserialiseArray(response) {
const previouslyLinked = {};
const relationshipCache = {};
const included = [...response.data.map(item => ({
...item,
relationships: {
...item.relationships
}
})), ...(response.included || [])];
for (let value of response.data) {
value = linkRelationships(value, included, previouslyLinked, relationshipCache);
if (value.attributes) value = deattribute(value);
response.data[response.data.indexOf(value)] = value;
}
return response;
}
function deserialise(response, options = {
hoistData: false
}) {
if (!response) return;
if (Array.isArray(response.data)) response = deserialiseArray(response);else if (response.included) response.data = linkRelationships(response.data, response.included);else if (typeof response.data === 'object' && response.data !== null) response.data = linkRelationships(response.data);
delete response.included;
if (response.data?.attributes) response.data = deattribute(response.data);
if (options.hoistData && response.data) {
response = hoistData(response);
}
return response;
}
export { deserialise };