Source: api/common/index.js

/**
 * @module cpb-api/common
 */

/**
 * summary reducer calculator
 * @param previous
 * @param current
 * @return {*}
 */
export const accumulator = (previous, current) => previous + current;

/**
 *
 * @param name
 * @return {number|undefined}
 */
export function getProductIdFromFileName(name) {
  if (!name || name.indexOf('.json') === -1) return undefined;
  // 10003054628/7000615813313.json
  const id = name.replace('.json', '').split('/').pop();
  if (id && isFinite(id)) return +id;
  return undefined;
}

/**
 * groups files by name, adds versions array to each file, & calculates the stats (counters)
 * @param {Object[]} files  - array of files returned by gcs api
 * @param {?boolean} [versions=true]
 * @returns {GroupedFiles}
 * @example
 * [
 *   [ 1864679522368 ], // products
 *   [ 1545018852513735 ], //deletedProducts
 *   {  // productConfigs
 *      "1864679522368": {
 *       "name": "1864679522368.json",
 *        "path": "10039296064/1864679522368.json",
 *        "versions": [
 *                      {
 *                 "id": "custom-product-builder/10039296064/1864679522368.json/1545026853482573",
 *                 "generation": 1545026853482573,
 *                 "metadata": {
 *                     "name": "10039296064/1864679522368.json",
 *                     "md5Hash": "hJ4zFV1TRwWqBz6h4NjHhw==",
 *                     "crc32c": "F6w/kw==",
 *                     "timeCreated": "2018-12-17T06:07:33.482Z",
 *                     "updated": "2018-12-17T06:07:33.482Z",
 *                     "timeDeleted": "2018-12-17T06:08:26.690Z"
 *                 },
 *                 "isDeleted": true,
 *                 "isCurrent": false,
 *                 "size": 13743,
 *                 "url":
 *   "https://storage.googleapis.com/download/storage/v1/b/custom-product-builder/o/10039296064%2F1864679522368.json?generation=1545026853482573&alt=media"
 *                 },
 *                 {
 *                   "id": "custom-product-builder/10039296064/1864679522368.json/1545026906691128",
 *                   "generation": 1545026906691128,
 *                   "metadata": {
 *                     "name": "10039296064/1864679522368.json",
 *                     "md5Hash": "VUowmTd+trJuzWnIXk3T9Q==",
 *                     "crc32c": "Aov/rA==",
 *                     "timeCreated": "2018-12-17T06:08:26.690Z",
 *                     "updated": "2018-12-17T06:08:26.690Z"
 *                   },
 *                 "isDeleted": false,
 *                 "isCurrent": true,
 *                 "size": 13879,
 *                 "url":
 *   "https://storage.googleapis.com/download/storage/v1/b/custom-product-builder/o/10039296064%2F1864679522368.json?generation=1545026906691128&alt=media"
 *                 }
 */
export function groupFiles(files, versions = true) {
  const data = {},
    productConfigs = {};

  for (const file of files) {
    const name = file.name.split('/').pop(),
      productId = getProductIdFromFileName(name);

    if (productId) {
      productConfigs[productId] = productConfigs[productId] || {
        name,
        path: file.name,
        versions: [],
      };
      productConfigs[productId].versions.push(file);
    }
    data[name] = data[name] || {
      name,
      versions: [],
    };
    data[name].versions.push(file);
  }

  for (const [key, val] of Object.entries(data)) {
    const activeVersion = val.versions.find(a => !a.metadata.timeDeleted);
    data[key].isDeleted = !activeVersion;
    if (activeVersion) {
      data[key].currentFileSize = +activeVersion.currentFileSize;
      data[key].generation = +activeVersion.metadata.generation;
      data[key].url = activeVersion.metadata.mediaLink;
    }

    for (const version of data[key].versions) {
      version.isDeleted = !!version.metadata.timeDeleted;
      version.isCurrent = !version.isDeleted;
      version.size = +version.metadata.size;
      version.url = version.metadata.mediaLink;
      version.generation = +version.generation;

      for (const attribute of ['name', 'bucket', 'currentFileSize']) {
        delete version[attribute];
      }

      // removing versions.metadata properties
      for (const attribute of [
        'id', // 'name',
        // 'md5Hash',
        // 'crc32c',
        'etag',
        'generation',
        'selfLink',
        'mediaLink',
        'contentType',
        'bucket',
        'kind',
        'storageClass',
        'timeStorageClassUpdated',
        'metageneration',
        'size',
      ]) {
        delete version.metadata[attribute];
      }
    }
    data[key].totalSize = data[key].versions.map(f => +f.size).reduce(accumulator, 0);

    if (!versions) delete data[key].versions;
    else {
      data[key].previousFileVersionsCount = data[key].versions.length - 1;
      data[key].previousFileVersionsSize = data[key].totalSize - data[key].currentFileSize;
    }
  }

  return [Object.values(data).filter(f => !f.isDeleted), Object.values(data).filter(f => f.isDeleted), productConfigs];
}

/**
 * gets array of shopify product id's from the files on cloud storage bucket where the dir is `request.params('id')`
 * with trailing forward slash appended ( the `prefix` )
 * @param {Object[]} files - array of files returned by gcs api
 * @return {Array(number[], number[])} ids, deletedId - shopify product ids
 */
export function getProductIdsFromFiles(files) {
  const products = {},
    deletedProducts = {};

  for (const entry of files) {
    const id = getProductIdFromFileName(entry.name);
    if (id) {
      if (!entry.isDeleted) products[id] = id;
      else deletedProducts[id] = id;
    }
  }
  return [Object.keys(products).map(a => +a), Object.keys(deletedProducts).map(a => +a)];
}