"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.EntityTypeError = void 0;
exports.camelToSnake = camelToSnake;
exports.convertMapToObject = convertMapToObject;
exports.createEditionGroupForNewEdition = createEditionGroupForNewEdition;
exports.diffRevisions = diffRevisions;
exports.formatDate = formatDate;
exports.isIterable = isIterable;
exports.parseDate = parseDate;
exports.promiseProps = promiseProps;
exports.snakeToCamel = snakeToCamel;
exports.snakeToCamelID = snakeToCamelID;
exports.truncateTables = truncateTables;
exports.validateEntityType = validateEntityType;
var _padStart2 = _interopRequireDefault(require("lodash/padStart"));
var _toNumber2 = _interopRequireDefault(require("lodash/toNumber"));
var _sortBy2 = _interopRequireDefault(require("lodash/sortBy"));
var _isArray2 = _interopRequireDefault(require("lodash/isArray"));
var _isString2 = _interopRequireDefault(require("lodash/isString"));
var _snakeCase2 = _interopRequireDefault(require("lodash/snakeCase"));
var _camelCase2 = _interopRequireDefault(require("lodash/camelCase"));
var _reduce2 = _interopRequireDefault(require("lodash/reduce"));
var _immutable = require("immutable");
var _deepDiff = require("deep-diff");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/*
* Copyright (C) 2015-2017 Ben Ockmore
* 2015 Sean Burke
*
* 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 snakeToCamel(attrs) {
return (0, _reduce2.default)(attrs, (result, val, key) => {
let newKey;
if (key.indexOf('_') === 0) {
newKey = `_${(0, _camelCase2.default)(key.substring(1))}`;
} else {
newKey = (0, _camelCase2.default)(key);
}
result[newKey] = val;
return result;
}, {});
}
function snakeToCamelID(attrs) {
return (0, _reduce2.default)(attrs, (result, val, key) => {
let newKey;
if (key.indexOf('_') === 0) {
newKey = `_${(0, _camelCase2.default)(key.substring(1))}`;
} else {
newKey = (0, _camelCase2.default)(key);
}
if (newKey !== 'bbid' && newKey !== 'id') {
newKey = newKey.replace('Bbid', 'BBID').replace('Id', 'ID');
}
result[newKey] = val;
return result;
}, {});
}
function camelToSnake(attrs) {
return (0, _reduce2.default)(attrs, (result, val, key) => {
let newKey;
if (key.indexOf('_') === 0) {
newKey = `_${(0, _snakeCase2.default)(key.substring(1))}`;
} else {
newKey = (0, _snakeCase2.default)(key);
}
result[newKey] = val;
return result;
}, {});
}
class EntityTypeError extends Error {
constructor(message) {
super(message);
this.name = 'EntityTypeError';
this.message = message;
this.stack = new Error().stack;
}
}
exports.EntityTypeError = EntityTypeError;
function validateEntityType(model) {
if (model.get('_type') !== model.typeId) {
throw new Error(`Entity ${model.get('bbid')} is not a ${model.typeId}`);
}
}
async function truncateTables(bookshelf, tables) {
for (const table of tables) {
// eslint-disable-next-line no-await-in-loop
await bookshelf.knex.raw(`TRUNCATE ${table} CASCADE`);
}
}
function diffRevisions(base, other, includes) {
function diffFilter(path, key) {
if ((0, _isString2.default)(key)) {
return key.startsWith('_pivot');
}
return false;
}
function sortEntityData(data) {
const aliasesPresent = data.aliasSet && (0, _isArray2.default)(data.aliasSet.aliases);
if (aliasesPresent) {
data.aliasSet.aliases = (0, _sortBy2.default)(data.aliasSet.aliases, 'id');
}
const identifiersPresent = data.identifierSet && (0, _isArray2.default)(data.identifierSet.identifiers);
if (identifiersPresent) {
data.identifierSet.identifiers = (0, _sortBy2.default)(data.identifierSet.identifiers, ['value', 'type.label']);
}
const relationshipsPresent = data.relationshipSet && (0, _isArray2.default)(data.relationshipSet.relationships);
if (relationshipsPresent) {
data.relationshipSet.relationships = (0, _sortBy2.default)(data.relationshipSet.relationships, 'id');
}
return data;
}
const baseDataPromise = base.related('data').fetch({
require: false,
withRelated: includes
});
if (!other) {
return baseDataPromise.then(baseData => (0, _deepDiff.diff)({}, baseData ? sortEntityData(baseData.toJSON()) : {}, diffFilter));
}
const otherDataPromise = other.related('data').fetch({
require: false,
withRelated: includes
});
return Promise.all([baseDataPromise, otherDataPromise]).then(([baseData, otherData]) => (0, _deepDiff.diff)(otherData ? sortEntityData(otherData.toJSON()) : {}, baseData ? sortEntityData(baseData.toJSON()) : {}, diffFilter));
}
const YEAR_STR_LENGTH = 6;
const MONTH_STR_LENGTH = 2;
const DAY_STR_LENGTH = 2;
/**
* Produce an ISO 8601-2004 formatted string for a date.
* @param {number} year - A calendar year.
* @param {number} [month] - A calendar month.
* @param {number} [day] - A calendar day of month.
* @returns {string} The provided date formatted as an ISO 8601-2004 year or calendar date.
*/
function formatDate(year, month, day) {
if ((!year || isNaN((0, _toNumber2.default)(year))) && year !== 0) {
return null;
}
const isCommonEraDate = Math.sign(year) === 1 || Math.sign(year) === 0;
// eslint-disable-next-line max-len
const yearString = `${isCommonEraDate ? '+' : '-'}${(0, _padStart2.default)(Math.abs(year).toString(), YEAR_STR_LENGTH, '0')}`;
if (!month || isNaN((0, _toNumber2.default)(month))) {
return `${yearString}`;
}
const monthString = (0, _padStart2.default)(month.toString(), MONTH_STR_LENGTH, '0');
if (!day || isNaN((0, _toNumber2.default)(day))) {
return `${yearString}-${monthString}`;
}
const dayString = (0, _padStart2.default)(day.toString(), DAY_STR_LENGTH, '0');
return `${yearString}-${monthString}-${dayString}`;
}
/**
* Split ISO 8601 calendar dates or years into a numerical array.
* @param {string} date - A date of the format 'YYYY', 'YYYY-MM', or 'YYYY-MM-DD'.
* @returns {Array<number| null>} - Year, month, and day of month respectively.
*/
function parseDate(date) {
if (!date) {
return [null, null, null];
}
const parts = date.toString().split('-');
// A leading minus sign denotes a BC date
// This creates an empty part that needs to be removed,
// and requires us to add the negative sign back for the year
// We ensure parts[0] is a number and not for example an empty string
if (parts[0] === '') {
parts.shift();
parts[0] = -parseInt(parts[0], 10);
}
// Incorrect format
if (parts.length < 1 || parts.length > 3) {
return [null, null, null];
}
let padding = [];
if (parts.length === 1) {
padding = [null, null];
} else if (parts.length === 2) {
padding = [null];
}
return parts.map(part => {
const parsed = parseInt(part, 10);
return isNaN(parsed) ? null : parsed;
}).concat(padding);
}
/**
* Create a new Edition Group for an Edition.
* The Edition Group will be part of the same revision, and will have the same
* alias set and author credit for that revision
* Subsequent changes to the alias set or author credit for either entity will
* only impact that entity's new revision.
* @param {Bookshelf} orm - The Bookshelf ORM
* @param {Transaction} transacting - The Bookshelf/Knex SQL transaction in progress
* @param {number|string} aliasSetId - The id of the new edition's alias set
* @param {number|string} revisionId - The id of the new edition's revision
* @param {number|string} authorCreditId - The id of the new edition's author credit
* @param {boolean} creditSection - The state of author credit section of the new edition
* @returns {string} BBID of the newly created Edition Group
*/
async function createEditionGroupForNewEdition(orm, transacting, aliasSetId, revisionId, authorCreditId, creditSection) {
const Entity = orm.model('Entity');
const EditionGroup = orm.model('EditionGroup');
const newEditionGroupEntity = await new Entity({
type: 'EditionGroup'
}).save(null, {
method: 'insert',
transacting
});
const bbid = newEditionGroupEntity.get('bbid');
await new EditionGroup({
aliasSetId,
authorCreditId,
bbid,
creditSection,
revisionId
}).save(null, {
method: 'insert',
transacting
});
return bbid;
}
/**
* Replacement for Bluebird's Promise.props
* @param {Object} promiseObj - an object containing string keys and promises
* to be resolved as the values
* @returns {Object} an object containing the same keys, but resolved promises
*/
async function promiseProps(promiseObj) {
const resolvedKeyValuePairs = await Promise.all(Object.entries(promiseObj).map(([key, val]) => Promise.resolve(val).then(x => [key, x])));
return Object.fromEntries(resolvedKeyValuePairs);
}
function isIterable(testVal) {
return _immutable.Iterable.isIterable(testVal);
}
function convertMapToObject(value) {
return isIterable(value) ? value.toJS() : value;
}