func/set.js

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createNewRelationshipAttributeSetWithItems = createNewRelationshipAttributeSetWithItems;
exports.createNewSetWithItems = createNewSetWithItems;
exports.getAddedItems = getAddedItems;
exports.getComparisonFunc = getComparisonFunc;
exports.getRemovedItems = getRemovedItems;
exports.getUnchangedItems = getUnchangedItems;
exports.removeItemsFromSet = void 0;
var _pick2 = _interopRequireDefault(require("lodash/pick"));
var _omit2 = _interopRequireDefault(require("lodash/omit"));
var _map2 = _interopRequireDefault(require("lodash/map"));
var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty"));
var _differenceWith2 = _interopRequireDefault(require("lodash/differenceWith"));
var _intersectionWith2 = _interopRequireDefault(require("lodash/intersectionWith"));
var _uniqWith2 = _interopRequireDefault(require("lodash/uniqWith"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
 * Copyright (C) 2018  Ben Ockmore
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/**
 * Returns a function which compares two object provided to it using the
 * comparison fields mentioned
 * @param  {Array<string>} compareFields - Comparison fields of two objects
 * @returns {Function} - Returns a comparison function
 */
function getComparisonFunc(compareFields) {
  /**
   * @param  {any} obj - Object for comparison
   * @param  {any} other - Object for comparison
   * @returns {boolean} Boolean value denoting objects are equal on fields
   */
  return function Cmp(obj, other) {
    for (const field of compareFields) {
      if (obj[field] !== other[field]) {
        return false;
      }
    }
    return true;
  };
}

/**
 * Get the intersection of two arrays of objects using a custom comparison
 * function. The two arrays represent two versions of a single set - one array
 * is the set before a particular change and the other is the same set after
 * that change.
 *
 * @param {Array<Item>} oldSet - The old array to compare
 * @param {Array<Item>} newSet - The new array to compare
 * @param {Function} comparisonFunc - Function to compare items from the two
 * arrays
 *
 * @returns {Array<Item>} - An array representing the intersection of the two
 * arrays
 */
function getUnchangedItems(oldSet, newSet, comparisonFunc) {
  return (0, _uniqWith2.default)((0, _intersectionWith2.default)(oldSet, newSet, comparisonFunc), comparisonFunc);
}

/**
 * Get any items in the new version of the set that aren't present in the old
 * version using a custom comparison function. The two arrays represent two
 * versions of a single set - one array is the set before a particular change
 * and the other is the same set after that change.
 *
 * @param {Array<Item>} oldSet - The old array to compare
 * @param {Array<Item>} newSet - The new array to compare
 * @param {Function} comparisonFunc - Function to compare items from the two
 * arrays
 *
 * @returns {Array<Item>} - An array representing the difference of the two
 * arrays
 */
function getAddedItems(oldSet, newSet, comparisonFunc) {
  return (0, _uniqWith2.default)((0, _differenceWith2.default)(newSet, oldSet, comparisonFunc), comparisonFunc);
}

/**
* Get any items in the old version of the set that aren't present in the new
* version using a custom comparison function. The two arrays represent two
* versions of a single set - one array is the set before a particular change
* and the other is the same set after that change.
 *
 * @param {Array<Item>} oldSet - The old array to compare
 * @param {Array<Item>} newSet - The new array to compare
 * @param {Function} comparisonFunc - Function to compare items from the two
 * arrays
 *
 * @returns {Array<Item>} - An array representing the difference of the two
 * arrays
 */
function getRemovedItems(oldSet, newSet, comparisonFunc) {
  return (0, _uniqWith2.default)((0, _differenceWith2.default)(oldSet, newSet, comparisonFunc), comparisonFunc);
}
const removeItemsFromSet = getRemovedItems;

// TODO: unchangedItems: ItemWithIdT, addedItems: ItemT
exports.removeItemsFromSet = removeItemsFromSet;
async function createNewSetWithItems(orm, transacting, SetModel, unchangedItems, addedItems, itemsAttribute, idAttribute = 'id') {
  if (!itemsAttribute) {
    throw Error('itemsAttribute must be set in createNewSetWithItems');
  }
  if ((0, _isEmpty2.default)(unchangedItems) && (0, _isEmpty2.default)(addedItems)) {
    return null;
  }
  const newSet = await new SetModel().save(null, {
    transacting
  });
  const newSetItemsCollection = await newSet.related(itemsAttribute).fetch({
    transacting
  });
  const newSetItemsCollectionAttached = await newSetItemsCollection.attach((0, _map2.default)(unchangedItems, idAttribute), {
    transacting
  });
  await Promise.all((0, _map2.default)(addedItems, ident => newSetItemsCollectionAttached.create((0, _omit2.default)(ident, idAttribute), {
    transacting
  })));
  return newSet;
}
async function createNewRelationshipAttributeSetWithItems(orm, transacting, SetModel, unchangedItems, addedItems, itemsAttribute, idAttribute = 'id') {
  const {
    RelationshipAttributeTextValue
  } = orm;
  if (!itemsAttribute) {
    throw Error('itemsAttribute must be set in createNewRelationshipAttributeSetWithItems');
  }
  if ((0, _isEmpty2.default)(unchangedItems) && (0, _isEmpty2.default)(addedItems)) {
    return null;
  }
  const newSet = await new SetModel().save(null, {
    transacting
  });
  const newSetItemsCollection = await newSet.related(itemsAttribute).fetch({
    transacting
  });
  const newSetItemsCollectionAttached = await newSetItemsCollection.attach((0, _map2.default)(unchangedItems, idAttribute), {
    transacting
  });
  await Promise.all((0, _map2.default)(addedItems, async ident => {
    const model = await newSetItemsCollectionAttached.create((0, _pick2.default)(ident, 'attributeType'), {
      transacting
    });
    const {
      value
    } = ident;
    await new RelationshipAttributeTextValue({
      attributeId: model.get('id'),
      textValue: value.textValue
    }).save(null, {
      method: 'insert',
      transacting
    });
    return model;
  }));
  return newSet;
}