lib/serializer.js
function handleIncludes (resp, includes, relations, options) {
  var app = options.app

  relations = utils.setIncludedRelations(relations, app)

  var resources = _.isArray(resp.data) ? resp.data : [resp.data]

  if (typeof includes === 'string') {
    includes = [includes]
  }

  if (!_.isArray(includes)) {
    throw RelUtils.getInvalidIncludesError(
      'JSON API unable to detect valid includes'
    )
  }

  var embedded = resources.map(function subsituteEmbeddedForIds (resource) {
    return includes.map(function (include) {
      var relation = relations[include]
      var includedRelations = relations[include].relations
      var propertyKey = relation.keyFrom
      var plural = ''
      if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) {
        var descriminator = relation.polymorphic.discriminator
        var discriminator = resource.attributes[descriminator]
        plural = utils.pluralForModel(app.models[discriminator])
      } else {
        plural = utils.pluralForModel(relation.modelTo)
      }
      var embeds = []

      // If relation is belongsTo then pk and fk are the other way around
      if (utils.relationFkOnModelFrom(relation)) {
        propertyKey = relation.keyTo
      }

      if (!relation) {
        throw RelUtils.getInvalidIncludesError(
          'Can\'t locate relationship "' + include + '" to include'
        )
      }

      resource.relationships[include] = resource.relationships[include] || {}

      if (resource.relationships[include] && resource.attributes[include]) {
        if (_.isArray(resource.attributes[include])) {
          embeds = resource.attributes[include].map(function (rel) {
            rel = utils.clone(rel)
            return createCompoundIncludes(
              rel,
              propertyKey,
              relation.keyTo,
              plural,
              includedRelations,
              options
            )
          })
          embeds = _.compact(embeds)
          const included = resource.attributes[include]
          resource.relationships[include].data = included.map(relData => {
            return {
              id: String(relData[propertyKey]),
              type: plural
            }
          })
        } else {
          var rel = utils.clone(resource.attributes[include])
          var compoundIncludes = createCompoundIncludes(
            rel,
            propertyKey,
            relation.keyFrom,
            plural,
            includedRelations,
            options
          )

          resource.relationships[include].data = {
            id: String(resource.attributes[include][propertyKey]),
            type: plural
          }
          embeds.push(compoundIncludes)
        }
        delete resource.attributes[relation.keyFrom]
        delete resource.attributes[relation.keyTo]
        delete resource.attributes[include]
      }
      return embeds
    })
  })

  if (embedded.length) {
    // This array may contain duplicate models if the same item is referenced multiple times in 'data'
    var duplicate = _.flattenDeep(embedded)
    // So begin with an empty array that will only contain unique items
    var unique = []
    // Iterate through each item in the first array
    duplicate.forEach(function (d) {
      // Count the number of items in the unique array with matching 'type' AND 'id'
      // Since we're adhering to the JSONAPI spec, both 'type' and 'id' can assumed to be present
      // Both 'type' and 'id' are needed for comparison because we could theoretically have objects of different
      // types who happen to have the same 'id', and those would not be considered duplicates
      var count = unique.filter(function (u) {
        return u.type === d.type && u.id === d.id
      }).length
      // If there are no matching entries, then add the item to the unique array
      if (count === 0) {
        unique.push(d)
      }
    })
    resp.included = unique
  }
}
function handleIncludes (resp, includes, relations, options) {
  var app = options.app

  relations = utils.setIncludedRelations(relations, app)

  var resources = _.isArray(resp.data) ? resp.data : [resp.data]

  if (typeof includes === 'string') {
    includes = [includes]
  }

  if (!_.isArray(includes)) {
    throw RelUtils.getInvalidIncludesError(
      'JSON API unable to detect valid includes'
    )
  }

  var embedded = resources.map(function subsituteEmbeddedForIds (resource) {
    return includes.map(function (include) {
      var relation = relations[include]
      var includedRelations = relations[include].relations
      var propertyKey = relation.keyFrom
      var plural = ''
      if (relation.polymorphic && utils.relationFkOnModelFrom(relation)) {
        var descriminator = relation.polymorphic.discriminator
        var discriminator = resource.attributes[descriminator]
        plural = utils.pluralForModel(app.models[discriminator])
      } else {
        plural = utils.pluralForModel(relation.modelTo)
      }
      var embeds = []

      // If relation is belongsTo then pk and fk are the other way around
      if (utils.relationFkOnModelFrom(relation)) {
        propertyKey = relation.keyTo
      }

      if (!relation) {
        throw RelUtils.getInvalidIncludesError(
          'Can\'t locate relationship "' + include + '" to include'
        )
      }

      resource.relationships[include] = resource.relationships[include] || {}

      if (resource.relationships[include] && resource.attributes[include]) {
        if (_.isArray(resource.attributes[include])) {
          embeds = resource.attributes[include].map(function (rel) {
            rel = utils.clone(rel)
            return createCompoundIncludes(
              rel,
              propertyKey,
              relation.keyTo,
              plural,
              includedRelations,
              options
            )
          })
          embeds = _.compact(embeds)
          const included = resource.attributes[include]
          resource.relationships[include].data = included.map(relData => {
            return {
              id: String(relData[propertyKey]),
              type: plural
            }
          })
        } else {
          var rel = utils.clone(resource.attributes[include])
          var compoundIncludes = createCompoundIncludes(
            rel,
            propertyKey,
            relation.keyFrom,
            plural,
            includedRelations,
            options
          )

          resource.relationships[include].data = {
            id: String(resource.attributes[include][propertyKey]),
            type: plural
          }
          embeds.push(compoundIncludes)
        }
        delete resource.attributes[relation.keyFrom]
        delete resource.attributes[relation.keyTo]
        delete resource.attributes[include]
      }
      return embeds
    })
  })

  if (embedded.length) {
    // This array may contain duplicate models if the same item is referenced multiple times in 'data'
    var duplicate = _.flattenDeep(embedded)
    // So begin with an empty array that will only contain unique items
    var unique = []
    // Iterate through each item in the first array
    duplicate.forEach(function (d) {
      // Count the number of items in the unique array with matching 'type' AND 'id'
      // Since we're adhering to the JSONAPI spec, both 'type' and 'id' can assumed to be present
      // Both 'type' and 'id' are needed for comparison because we could theoretically have objects of different
      // types who happen to have the same 'id', and those would not be considered duplicates
      var count = unique.filter(function (u) {
        return u.type === d.type && u.id === d.id
      }).length
      // If there are no matching entries, then add the item to the unique array
      if (count === 0) {
        unique.push(d)
      }
    })
    resp.included = unique
  }
}
function handleIncludes ( resp , includes , relations , options ) { var app = options . app relations = utils . setIncludedRelations ( relations , app ) var resources = _ . isArray ( resp . data ) ? resp . data : [ resp . data ] if ( typeof includes === 'string' ) { includes = [ includes ] } if ( ! _ . isArray ( includes ) ) { throw RelUtils . getInvalidIncludesError ( 'JSON API unable to detect valid includes' ) } var embedded = resources . map ( function subsituteEmbeddedForIds ( resource ) { return includes . map ( function ( include ) { var relation = relations [ include ] var includedRelations = relations [ include ] . relations var propertyKey = relation . keyFrom var plural = '' if ( relation . polymorphic && utils . relationFkOnModelFrom ( relation ) ) { var descriminator = relation . polymorphic . discriminator var discriminator = resource . attributes [ descriminator ] plural = utils . pluralForModel ( app . models [ discriminator ] ) } else { plural = utils . pluralForModel ( relation . modelTo ) } var embeds = [ ] // If relation is belongsTo then pk and fk are the other way around if ( utils . relationFkOnModelFrom ( relation ) ) { propertyKey = relation . keyTo } if ( ! relation ) { throw RelUtils . getInvalidIncludesError ( 'Can\'t locate relationship "' + include + '" to include' ) } resource . relationships [ include ] = resource . relationships [ include ] || { } if ( resource . relationships [ include ] && resource . attributes [ include ] ) { if ( _ . isArray ( resource . attributes [ include ] ) ) { embeds = resource . attributes [ include ] . map ( function ( rel ) { rel = utils . clone ( rel ) return createCompoundIncludes ( rel , propertyKey , relation . keyTo , plural , includedRelations , options ) } ) embeds = _ . compact ( embeds ) const included = resource . attributes [ include ] resource . relationships [ include ] . data = included . map ( relData => { return { id : String ( relData [ propertyKey ] ) , type : plural } } ) } else { var rel = utils . clone ( resource . attributes [ include ] ) var compoundIncludes = createCompoundIncludes ( rel , propertyKey , relation . keyFrom , plural , includedRelations , options ) resource . relationships [ include ] . data = { id : String ( resource . attributes [ include ] [ propertyKey ] ) , type : plural } embeds . push ( compoundIncludes ) } delete resource . attributes [ relation . keyFrom ] delete resource . attributes [ relation . keyTo ] delete resource . attributes [ include ] } return embeds } ) } ) if ( embedded . length ) { // This array may contain duplicate models if the same item is referenced multiple times in 'data' var duplicate = _ . flattenDeep ( embedded ) // So begin with an empty array that will only contain unique items var unique = [ ] // Iterate through each item in the first array duplicate . forEach ( function ( d ) { // Count the number of items in the unique array with matching 'type' AND 'id' // Since we're adhering to the JSONAPI spec, both 'type' and 'id' can assumed to be present // Both 'type' and 'id' are needed for comparison because we could theoretically have objects of different // types who happen to have the same 'id', and those would not be considered duplicates var count = unique . filter ( function ( u ) { return u . type === d . type && u . id === d . id } ) . length // If there are no matching entries, then add the item to the unique array if ( count === 0 ) { unique . push ( d ) } } ) resp . included = unique } }
Handles serializing the requested includes to a seperate included property
per JSON API spec.
@private
@memberOf {Serializer}
@param {Object} resp
@param {Array<String>|String}
@throws {Error}
@return {undefined}
Handles serializing the requested includes to a seperate included property per JSON API spec .