'use strict';

const { isNil, isPlainObject } = require('lodash/fp');
const { parseMultipartData } = require('@strapi/utils');

const parseBody = ctx => {
  if (ctx.is('multipart')) {
    return parseMultipartData(ctx);
  }

  const { data } = ctx.request.body || {};

  return { data };
};

const transformResponse = (resource, meta = {}, { contentType } = {}) => {
  if (isNil(resource)) {
    return resource;
  }

  return {
    data: transformEntry(resource, contentType),
    meta,
  };
};

const transformEntry = (entry, contentType) => {
  if (isNil(entry)) {
    return entry;
  }

  if (Array.isArray(entry)) {
    return entry.map(singleEntry => transformEntry(singleEntry, contentType));
  }

  if (!isPlainObject(entry)) {
    throw new Error('Entry must be an object');
  }

  const { id, ...properties } = entry;

  const attributeValues = {};

  for (const key in properties) {
    const property = properties[key];
    const attribute = contentType && contentType.attributes[key];

    if (attribute && attribute.type === 'relation') {
      const data = transformEntry(property, strapi.contentType(attribute.target));

      attributeValues[key] = { data };
    } else if (attribute && attribute.type === 'component') {
      const { id, attributes } = transformEntry(property, strapi.components[attribute.component]);
      attributeValues[key] = { id, ...attributes };
    } else if (attribute && attribute.type === 'dynamiczone') {
      if (Array.isArray(property)) {
        attributeValues[key] = property.map(subProperty => {
          const { id, attributes } = transformEntry(
            subProperty,
            strapi.components[subProperty.__component]
          );

          return { id, ...attributes };
        });
      } else {
        attributeValues[key] = property;
      }
    } else if (attribute && attribute.type === 'media') {
      const data = transformEntry(property, strapi.contentType('plugin::upload.file'));

      attributeValues[key] = { data };
    } else {
      attributeValues[key] = property;
    }
  }

  return {
    id,
    attributes: attributeValues,
    // NOTE: not necessary for now
    // meta: {},
  };
};

module.exports = {
  parseBody,
  transformResponse,
};

@@ -509,32 +509,234 @@
 form
-Entry = (entry, contentT
+Component = (data, component) =%3E %7B%0A  const res = transformEntry(data, component);%0A%0A  if (isNil(res)) %7B%0A    return res;%0A  %7D%0A%0A  const %7B id, attributes %7D = res;%0A  return %7B id, ...attributes %7D;%0A%7D;%0A%0Aconst transformEntry = (entry, t
 ype)
@@ -880,24 +880,17 @@
 eEntry, 
-contentT
+t
 ype));%0A 
@@ -1146,31 +1146,17 @@
 e = 
-contentType && contentT
+type && t
 ype.
@@ -1422,32 +1422,28 @@
     
-const %7B id, attributes %7D
+attributeValues%5Bkey%5D
  = t
@@ -1442,37 +1442,41 @@
 key%5D = transform
-Entry
+Component
 (property, strap
@@ -1515,60 +1515,8 @@
 %5D);%0A
-      attributeValues%5Bkey%5D = %7B id, ...attributes %7D;%0A
     
@@ -1585,29 +1585,21 @@
     if (
-Array.isArray
+isNil
 (propert
@@ -1647,292 +1647,179 @@
 erty
-.map(subProperty =%3E %7B%0A          const %7B id, attributes %7D = transformEntry(%0A            subProperty,%0A            strapi.components%5BsubProperty.__component%5D%0A          );%0A%0A          return %7B id, ...attributes %7D;%0A        %7D);%0A      %7D else %7B%0A        attributeValues%5Bkey%5D = property;%0A      %7D
+;%0A      %7D%0A%0A      attributeValues%5Bkey%5D = property.map(subProperty =%3E %7B%0A        return transformComponent(subProperty, strapi.components%5BsubProperty.__component%5D);%0A      %7D);
 %0A   

Handle empty values