UNPKG

jsonapi-serializer

Version:

A Node.js framework agnostic library for serializing your data to JSON API

127 lines (110 loc) 3.61 kB
'use strict'; var P = require('bluebird'); var _ = require('lodash'); var Inflector = require('./inflector'); module.exports = function (jsonapi, data, opts) { function isComplexType(obj) { return _.isArray(obj) || _.isPlainObject(obj); } function getValueForRelationship(relationshipData, included) { if (opts && relationshipData && opts[relationshipData.type]) { var valueForRelationshipFct = opts[relationshipData.type] .valueForRelationship; return valueForRelationshipFct(relationshipData, included); } else { return included; } } function findIncluded(relationshipData) { return new P(function (resolve) { if (!jsonapi.included || !relationshipData) { resolve(null); } var included = _.findWhere(jsonapi.included, { id: relationshipData.id, type: relationshipData.type }); if (included) { return P .all([extractAttributes(included), extractRelationships(included)]) .spread(function (attributes, relationships) { resolve(_.extend(attributes, relationships)); }); } else { return resolve(null); } }); } function keyForAttribute(attribute) { if (_.isPlainObject(attribute)) { return _.transform(attribute, function (result, value, key) { if (isComplexType(value)) { result[keyForAttribute(key)] = keyForAttribute(value); } else { result[keyForAttribute(key)] = value; } }); } else if (_.isArray(attribute)) { return attribute.map(function (attr) { if (isComplexType(attr)) { return keyForAttribute(attr); } else { return attr; } }); } else { if (_.isFunction(opts.keyForAttribute)) { return opts.keyForAttribute(attribute); } else { return Inflector.caserize(attribute, opts); } } } function extractAttributes(from) { var dest = keyForAttribute(from.attributes || {}); if ('id' in from) { dest.id = from.id; } return dest; } function extractRelationships(from) { if (!from.relationships) { return; } var dest = {}; return P .each(Object.keys(from.relationships), function (key) { var relationship = from.relationships[key]; if (_.isArray(relationship.data)) { return P .map(relationship.data, function (relationshipData) { return extractIncludes(relationshipData); }) .then(function (includes) { if (includes) { dest[keyForAttribute(key)] = includes; } }); } else { return extractIncludes(relationship.data) .then(function (include) { if (include) { dest[keyForAttribute(key)] = include; } }); } }) .thenReturn(dest); } function extractIncludes(relationshipData) { return findIncluded(relationshipData) .then(function (included) { var valueForRelationship = getValueForRelationship(relationshipData, included); if (valueForRelationship && _.isFunction(valueForRelationship.then)) { return valueForRelationship.then(function (value) { return value; }); } else { return valueForRelationship; } }); } this.perform = function () { return P .all([extractAttributes(data), extractRelationships(data)]) .spread(function (attributes, relationships) { return _.extend(attributes, relationships); }); }; };