server/helpers/utils.js

"use strict";

require("core-js/modules/es.array.slice.js");
require("core-js/modules/es.array.from.js");
require("core-js/modules/es.symbol.js");
require("core-js/modules/es.symbol.description.js");
require("core-js/modules/es.symbol.iterator.js");
require("core-js/modules/es.weak-map.js");
require("core-js/modules/es.object.get-own-property-descriptor.js");
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.attachAttributes = attachAttributes;
exports.createEntityPageTitle = createEntityPageTitle;
exports.entityToOption = entityToOption;
exports.filterIdentifierTypesByEntity = filterIdentifierTypesByEntity;
exports.generateIdenfierState = generateIdenfierState;
exports.getAdditionalRelations = getAdditionalRelations;
exports.getDateBeforeDays = getDateBeforeDays;
exports.getIdByField = getIdByField;
exports.getIdByLabel = getIdByLabel;
exports.getIntFromQueryParams = getIntFromQueryParams;
exports.incrementEditorEditCountById = incrementEditorEditCountById;
exports.parseInitialState = parseInitialState;
exports.parseLanguages = parseLanguages;
exports.parseQuery = parseQuery;
exports.searchOption = searchOption;
exports.template = template;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
require("core-js/modules/es.array.iterator.js");
require("core-js/modules/es.object.to-string.js");
require("core-js/modules/es.set.js");
require("core-js/modules/es.string.iterator.js");
require("core-js/modules/web.dom-collections.iterator.js");
require("core-js/modules/es.array.filter.js");
require("core-js/modules/web.dom-collections.for-each.js");
require("core-js/modules/es.array.join.js");
require("core-js/modules/es.function.name.js");
require("core-js/modules/es.promise.js");
require("core-js/modules/es.parse-int.js");
require("core-js/modules/es.regexp.exec.js");
require("core-js/modules/es.string.replace.js");
require("core-js/modules/web.url-search-params.js");
require("core-js/modules/es.array.includes.js");
require("core-js/modules/es.string.includes.js");
require("core-js/modules/es.object.assign.js");
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _upperFirst2 = _interopRequireDefault(require("lodash/upperFirst"));
var _isNil2 = _interopRequireDefault(require("lodash/isNil"));
var search = _interopRequireWildcard(require("../../common/helpers/search"));
var _utils = require("../../common/helpers/utils");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } /*
                                                                                                                                                                                         * Copyright (C) 2015       Ben Ockmore
                                                                                                                                                                                         *               2015-2017  Sean Burke
                                                                                                                                                                                         				 2019       Akhilesh Kumar (@akhilesh26)
                                                                                                                                                                                         				 2020		Prabal Singh
                                                                                                                                                                                         *
                                                                                                                                                                                         * 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.
                                                                                                                                                                                         */
function getDateBeforeDays(days) {
  var date = new Date();
  date.setDate(date.getDate() - days);
  return date;
}
function filterIdentifierTypesByEntity(identifierTypes, entity) {
  var typesOnEntity = new Set();
  if (!entity.identifierSet || entity.identifierSet.identifiers.length < 1) {
    /*
     * If there are no identifiers, skip the work of trying to add types
     * which shouldn't be on this entity.
     */
    return (0, _utils.filterIdentifierTypesByEntityType)(identifierTypes, entity.type);
  }
  var _iterator = _createForOfIteratorHelper(entity.identifierSet.identifiers),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var identifier = _step.value;
      typesOnEntity.add(identifier.type.id);
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return identifierTypes.filter(function (type) {
    return type.entityType === entity.type || typesOnEntity.has(type.id);
  });
}

/**
 * Helper-function / template-tag that allows the values of an object that
 * is passed in at a later time to be interpolated into a
 * string.
 *
 * Cribbed from MDN documentation on template literals:
 * https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals
 *
 * @param {string[]} strings - Array of string literals from template
 * @returns {function(*)} - Takes an object/array as an argument.
 * When invoked, it will return a string with all the key names from
 * the tagged template literal replaced with their corresponding values
 * from the newly passed in object.
 */

function template(strings) {
  for (var _len = arguments.length, keys = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    keys[_key - 1] = arguments[_key];
  }
  return function (values) {
    var result = [strings[0]];
    keys.forEach(function (key, i) {
      result.push(values[key], strings[i + 1]);
    });
    return result.join('');
  };
}

/**
 * Generates a page title for an entity row
 *
 * @param {object} entity - Entity object
 * @param {string} titleForUnnamed - Fallback title in case entity has no name
 * @param {function} templateForNamed - Accepts an object with a name field and
 * uses it to generate a title string
 * @returns {string} - Title string
 */
function createEntityPageTitle(entity, titleForUnnamed, templateForNamed) {
  /**
   * User-visible strings should _never_ be created by concatenation; when we
   * start to implement localization, it will create problems for users of
   * many languages. This helper is here to make it a little easier to do the
   * right thing.
   */
  var title = titleForUnnamed;

  // Accept template with a "name" replacement field
  if (entity && entity.defaultAlias && entity.defaultAlias.name) {
    title = templateForNamed({
      name: entity.defaultAlias.name
    });
  }
  return title;
}

/**
 * Adds 1 to the edit count of the specified editor
 *
 * @param {object} orm - the BookBrainz ORM, initialized during app setup
 * @param {string} id - row ID of editor to be updated
 * @param {object} transacting - Bookshelf transaction object (must be in
 * progress)
 * @returns {Promise} - Resolves to the updated editor model
 */
function incrementEditorEditCountById(orm, id, transacting) {
  var Editor = orm.Editor;
  return new Editor({
    id: id
  }).fetch({
    require: true,
    transacting: transacting
  }).then(function (editor) {
    editor.incrementEditCount();
    return editor.save(null, {
      transacting: transacting
    });
  }).catch(Editor.NotFoundError, function (err) {
    return new Promise(function (resolve, reject) {
      return reject(err);
    });
  });
}

/**
 * Return additional relations to withRelated array according to modelType
 *
 * @param {string} modelType - type of the model or entity
 * @returns {array} array of additional relations
 */
function getAdditionalRelations(modelType) {
  if (modelType === 'Work') {
    return ['disambiguation', 'workType', 'languageSet.languages'];
  } else if (modelType === 'Edition') {
    return ['disambiguation', 'releaseEventSet.releaseEvents', 'identifierSet.identifiers.type', 'editionFormat'];
  }
  return [];
}

/**
 * Takes an entity and converts it to a format acceptable to react-select.
 *
 * @param {Object} entity the entity to convert
 * @returns {Object} the formatted data
 */
function entityToOption(entity) {
  return (0, _isNil2.default)(entity) ? null : {
    defaultAlias: entity.defaultAlias,
    disambiguation: entity.disambiguation ? entity.disambiguation.comment : null,
    id: entity.bbid,
    text: entity.defaultAlias ? entity.defaultAlias.name : '(unnamed)',
    type: entity.type
  };
}

/**
 * Takes an array of relationships and attach the deeply nested
 * relationship attributes to the first level of the relationship object.
 *
 * @param {Array} relationships the array of relationships
 */
function attachAttributes(relationships) {
  relationships.forEach(function (relationship) {
    var _relationship$attribu;
    if ((_relationship$attribu = relationship.attributeSet) !== null && _relationship$attribu !== void 0 && _relationship$attribu.relationshipAttributes) {
      relationship.attributeSet.relationshipAttributes.forEach(function (attribute) {
        relationship["".concat(attribute.type.name)] = attribute.value.textValue;
      });
    }
  });
}

/**
 * Fetch id related with label
 *
 * @param {object[]} fromOptions - Options
 * @param {string} label - related label
 * @param {string} keyName - key associated
 * @returns {number} - assigned id
 */
function getIdByLabel(fromOptions, label, keyName) {
  var _iterator2 = _createForOfIteratorHelper(fromOptions),
    _step2;
  try {
    for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
      var option = _step2.value;
      if (option[keyName] === label) {
        return option.id;
      }
    }
  } catch (err) {
    _iterator2.e(err);
  } finally {
    _iterator2.f();
  }
  return null;
}

/**
 * Fetch Id of a model using field value
 *
 * @param {object} model - Model  eg. Language
 * @param {string} fieldName - given field eg. name
 * @param {string} fieldValue - given field value eg. English
 * @returns {Promise} - Resolves to required id
 */
function getIdByField(_x, _x2, _x3) {
  return _getIdByField.apply(this, arguments);
}
/**
 * Generate Identifier state from req body
 *
 * @param {object} sourceIdentifierState - source state in format of t{typeId}:value
 * @returns {object} - correctly formatted identifierEditor state
 */
function _getIdByField() {
  _getIdByField = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(model, fieldName, fieldValue) {
    var _yield$model$query$fe, _yield$model$query$fe2;
    return _regenerator.default.wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return model.query({
              where: (0, _defineProperty2.default)({}, fieldName, fieldValue)
            }).fetch({
              require: false
            });
          case 2:
            _context.t2 = _yield$model$query$fe2 = _context.sent;
            _context.t1 = _context.t2 === null;
            if (_context.t1) {
              _context.next = 6;
              break;
            }
            _context.t1 = _yield$model$query$fe2 === void 0;
          case 6:
            if (!_context.t1) {
              _context.next = 10;
              break;
            }
            _context.t3 = void 0;
            _context.next = 11;
            break;
          case 10:
            _context.t3 = _yield$model$query$fe2.get('id');
          case 11:
            _context.t4 = _yield$model$query$fe = _context.t3;
            _context.t0 = _context.t4 !== null;
            if (!_context.t0) {
              _context.next = 15;
              break;
            }
            _context.t0 = _yield$model$query$fe !== void 0;
          case 15:
            if (!_context.t0) {
              _context.next = 19;
              break;
            }
            _context.t5 = _yield$model$query$fe;
            _context.next = 20;
            break;
          case 19:
            _context.t5 = null;
          case 20:
            return _context.abrupt("return", _context.t5);
          case 21:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return _getIdByField.apply(this, arguments);
}
function generateIdenfierState(sourceIdentifierState) {
  var index = 0;
  var identifierState = {};
  for (var typeKey in sourceIdentifierState) {
    if (Object.prototype.hasOwnProperty.call(sourceIdentifierState, typeKey)) {
      identifierState["".concat(index)] = {
        type: parseInt(typeKey.replace('t', ''), 10),
        value: sourceIdentifierState[typeKey]
      };
      index++;
    }
  }
  return identifierState;
}

/**
 * Generate EntitySection Language state from req body
 *
 * @param {object} sourceEntitySection - source entity section state in format of languages{index}:value
 * @param {object} orm - orm object
 *  @returns {Promise} - Resolves to modified state
 */
function parseLanguages(_x4, _x5) {
  return _parseLanguages.apply(this, arguments);
}
/**
 * Generate react-select option from query
 * @param {object} orm - orm
 * @param {string} type - type eg. area
 * @param {string} query - query string
 * @param {string} idKey - key corresponding to id
 * @param {boolean} exactMatch - exact matching the query string
 * @returns {Promise} - resolves to option object
 */
function _parseLanguages() {
  _parseLanguages = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(sourceEntitySection, orm) {
    var Language, languages, langKey;
    return _regenerator.default.wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            if (sourceEntitySection) {
              _context2.next = 2;
              break;
            }
            return _context2.abrupt("return", sourceEntitySection);
          case 2:
            Language = orm.Language;
            languages = [];
            _context2.t0 = _regenerator.default.keys(sourceEntitySection);
          case 5:
            if ((_context2.t1 = _context2.t0()).done) {
              _context2.next = 19;
              break;
            }
            langKey = _context2.t1.value;
            if (!Object.prototype.hasOwnProperty.call(sourceEntitySection, langKey)) {
              _context2.next = 17;
              break;
            }
            if (!langKey.includes('languages')) {
              _context2.next = 17;
              break;
            }
            _context2.t2 = languages;
            _context2.t3 = (0, _upperFirst2.default)(sourceEntitySection[langKey]);
            _context2.next = 13;
            return getIdByField(Language, 'name', (0, _upperFirst2.default)(sourceEntitySection[langKey]));
          case 13:
            _context2.t4 = _context2.sent;
            _context2.t5 = {
              label: _context2.t3,
              value: _context2.t4
            };
            _context2.t2.push.call(_context2.t2, _context2.t5);
            delete sourceEntitySection[langKey];
          case 17:
            _context2.next = 5;
            break;
          case 19:
            sourceEntitySection.languages = languages;
            return _context2.abrupt("return", sourceEntitySection);
          case 21:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2);
  }));
  return _parseLanguages.apply(this, arguments);
}
function searchOption(_x6, _x7, _x8) {
  return _searchOption.apply(this, arguments);
}
/**
 * Parse NameSection, IdentifierEditor, AnnotationSection state from request body
 *
 * @param {object} req - Request object
 * @param {string} type - entity type
 * @returns {Promise} - Resolves to Entity initialState
 */
function _searchOption() {
  _searchOption = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee3(orm, type, query) {
    var idKey,
      exactMatch,
      results,
      firstMatch,
      option,
      _args3 = arguments;
    return _regenerator.default.wrap(function _callee3$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            idKey = _args3.length > 3 && _args3[3] !== undefined ? _args3[3] : 'id';
            exactMatch = _args3.length > 4 && _args3[4] !== undefined ? _args3[4] : false;
            if (!exactMatch) {
              _context3.next = 8;
              break;
            }
            _context3.next = 5;
            return search.checkIfExists(orm, query, type);
          case 5:
            results = _context3.sent;
            _context3.next = 11;
            break;
          case 8:
            _context3.next = 10;
            return search.autocomplete(orm, query, type, 1);
          case 10:
            results = _context3.sent;
          case 11:
            if (!results.length) {
              _context3.next = 15;
              break;
            }
            firstMatch = results[0];
            option = {
              disambiguation: idKey === 'id' ? firstMatch.disambiguation.comment : null,
              id: firstMatch[idKey],
              text: firstMatch.defaultAlias.name,
              type: firstMatch.type
            };
            return _context3.abrupt("return", option);
          case 15:
            return _context3.abrupt("return", null);
          case 16:
          case "end":
            return _context3.stop();
        }
      }
    }, _callee3);
  }));
  return _searchOption.apply(this, arguments);
}
function parseInitialState(_x9, _x10) {
  return _parseInitialState.apply(this, arguments);
}
function _parseInitialState() {
  _parseInitialState = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee4(req, type) {
    var emptyState, entity, orm, Language, initialState;
    return _regenerator.default.wrap(function _callee4$(_context4) {
      while (1) {
        switch (_context4.prev = _context4.next) {
          case 0:
            emptyState = {
              nameSection: {
                disambiguation: '',
                exactMatches: null,
                language: null,
                name: '',
                searchResults: null,
                sortName: ''
              }
            };
            entity = (0, _utils.unflatten)(req.body);
            orm = req.app.locals.orm;
            Language = orm.Language; // NameSection State
            initialState = Object.assign(emptyState, entity); // We allow Editions (but not other entities) to have the same primary name as another Edition without requiring a disambiguation
            if (!(initialState.nameSection.name && type !== 'edition')) {
              _context4.next = 12;
              break;
            }
            _context4.next = 8;
            return search.autocomplete(orm, initialState.nameSection.name, type, 10);
          case 8:
            initialState.nameSection.searchResults = _context4.sent;
            _context4.next = 11;
            return search.checkIfExists(orm, initialState.nameSection.name, type);
          case 11:
            initialState.nameSection.exactMatches = _context4.sent;
          case 12:
            if (!initialState.nameSection.language) {
              _context4.next = 16;
              break;
            }
            _context4.next = 15;
            return getIdByField(Language, 'name', initialState.nameSection.language);
          case 15:
            initialState.nameSection.language = _context4.sent;
          case 16:
            // IdentifierEditor State
            if (initialState.identifierEditor) {
              initialState.identifierEditor = generateIdenfierState(initialState.identifierEditor);
            }
            // AnnotationSection State
            if (initialState.annotationSection) {
              initialState.annotationSection = {
                content: initialState.annotationSection
              };
            }
            // SubmissionSection State
            if (initialState.submissionSection) {
              initialState.submissionSection = {
                note: initialState.submissionSection,
                submitError: '',
                submitted: false
              };
            }
            return _context4.abrupt("return", initialState);
          case 20:
          case "end":
            return _context4.stop();
        }
      }
    }, _callee4);
  }));
  return _parseInitialState.apply(this, arguments);
}
function parseQuery(url) {
  return new URLSearchParams(url.replace(/^.+?\?/, ''));
}
function getIntFromQueryParams(query, name) {
  var fallback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
  return parseInt(query.get(name), 10) || fallback;
}
//# sourceMappingURL=utils.js.map