diff --git a/services/document-updater/.eslintrc b/services/document-updater/.eslintrc index 2e945d6ffb..76dad1561d 100644 --- a/services/document-updater/.eslintrc +++ b/services/document-updater/.eslintrc @@ -8,7 +8,7 @@ "prettier/standard" ], "parserOptions": { - "ecmaVersion": 2017 + "ecmaVersion": 2018 }, "plugins": [ "mocha", diff --git a/services/document-updater/app/js/HttpController.js b/services/document-updater/app/js/HttpController.js index 646a8578df..d2904eb898 100644 --- a/services/document-updater/app/js/HttpController.js +++ b/services/document-updater/app/js/HttpController.js @@ -330,19 +330,23 @@ function updateProject(req, res, next) { userId, docUpdates, fileUpdates, + updates, version } = req.body logger.log( - { projectId, docUpdates, fileUpdates, version }, + { projectId, updates, docUpdates, fileUpdates, version }, 'updating project via http' ) - + const allUpdates = _mergeUpdates( + docUpdates || [], + fileUpdates || [], + updates || [] + ) ProjectManager.updateProjectWithLocks( projectId, projectHistoryId, userId, - docUpdates, - fileUpdates, + allUpdates, version, (error) => { timer.done() @@ -412,3 +416,23 @@ function flushQueuedProjects(req, res, next) { } }) } + +/** + * Merge updates from the previous project update interface (docUpdates + + * fileUpdates) and the new update interface (updates). + */ +function _mergeUpdates(docUpdates, fileUpdates, updates) { + const mergedUpdates = [] + for (const update of docUpdates) { + const type = update.docLines != null ? 'add-doc' : 'rename-doc' + mergedUpdates.push({ type, ...update }) + } + for (const update of fileUpdates) { + const type = update.url != null ? 'add-file' : 'rename-file' + mergedUpdates.push({ type, ...update }) + } + for (const update of updates) { + mergedUpdates.push(update) + } + return mergedUpdates +} diff --git a/services/document-updater/app/js/ProjectManager.js b/services/document-updater/app/js/ProjectManager.js index 2955904adb..07284a692a 100644 --- a/services/document-updater/app/js/ProjectManager.js +++ b/services/document-updater/app/js/ProjectManager.js @@ -1,18 +1,3 @@ -/* eslint-disable - camelcase, - handle-callback-err, - no-unused-vars, -*/ -// TODO: This file was created by bulk-decaffeinate. -// Fix any style issues and re-enable lint. -/* - * decaffeinate suggestions: - * DS101: Remove unnecessary use of Array.from - * DS102: Remove unnecessary code created because of implicit returns - * DS207: Consider shorter variations of null checks - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ -let ProjectManager const RedisManager = require('./RedisManager') const ProjectHistoryRedisManager = require('./ProjectHistoryRedisManager') const DocumentManager = require('./DocumentManager') @@ -22,372 +7,300 @@ const logger = require('logger-sharelatex') const Metrics = require('./Metrics') const Errors = require('./Errors') -module.exports = ProjectManager = { - flushProjectWithLocks(project_id, _callback) { - if (_callback == null) { - _callback = function (error) {} - } - const timer = new Metrics.Timer('projectManager.flushProjectWithLocks') - const callback = function (...args) { - timer.done() - return _callback(...Array.from(args || [])) - } +module.exports = { + flushProjectWithLocks, + flushAndDeleteProjectWithLocks, + queueFlushAndDeleteProject, + getProjectDocsTimestamps, + getProjectDocsAndFlushIfOld, + clearProjectState, + updateProjectWithLocks +} - return RedisManager.getDocIdsInProject(project_id, function ( - error, - doc_ids - ) { - if (error != null) { - return callback(error) - } - const jobs = [] - const errors = [] - for (const doc_id of Array.from(doc_ids || [])) { - ;((doc_id) => - jobs.push((callback) => - DocumentManager.flushDocIfLoadedWithLock( - project_id, - doc_id, - function (error) { - if (error != null && error instanceof Errors.NotFoundError) { - logger.warn( - { err: error, project_id, doc_id }, - 'found deleted doc when flushing' - ) - return callback() - } else if (error != null) { - logger.error( - { err: error, project_id, doc_id }, - 'error flushing doc' - ) - errors.push(error) - return callback() - } else { - return callback() - } - } - ) - ))(doc_id) - } +function flushProjectWithLocks(projectId, _callback) { + const timer = new Metrics.Timer('projectManager.flushProjectWithLocks') + const callback = function (...args) { + timer.done() + _callback(...args) + } - logger.log({ project_id, doc_ids }, 'flushing docs') - return async.series(jobs, function () { - if (errors.length > 0) { - return callback( - new Error('Errors flushing docs. See log for details') + RedisManager.getDocIdsInProject(projectId, (error, docIds) => { + if (error) { + return callback(error) + } + const errors = [] + const jobs = docIds.map((docId) => (callback) => { + DocumentManager.flushDocIfLoadedWithLock(projectId, docId, (error) => { + if (error instanceof Errors.NotFoundError) { + logger.warn( + { err: error, projectId, docId }, + 'found deleted doc when flushing' ) + callback() + } else if (error) { + logger.error({ err: error, projectId, docId }, 'error flushing doc') + errors.push(error) + callback() } else { - return callback(null) + callback() } }) }) - }, - flushAndDeleteProjectWithLocks(project_id, options, _callback) { - if (_callback == null) { - _callback = function (error) {} - } - const timer = new Metrics.Timer( - 'projectManager.flushAndDeleteProjectWithLocks' - ) - const callback = function (...args) { - timer.done() - return _callback(...Array.from(args || [])) - } - - return RedisManager.getDocIdsInProject(project_id, function ( - error, - doc_ids - ) { - if (error != null) { - return callback(error) - } - const jobs = [] - const errors = [] - for (const doc_id of Array.from(doc_ids || [])) { - ;((doc_id) => - jobs.push((callback) => - DocumentManager.flushAndDeleteDocWithLock( - project_id, - doc_id, - {}, - function (error) { - if (error != null) { - logger.error( - { err: error, project_id, doc_id }, - 'error deleting doc' - ) - errors.push(error) - } - return callback() - } - ) - ))(doc_id) + logger.log({ projectId, docIds }, 'flushing docs') + async.series(jobs, () => { + if (errors.length > 0) { + callback(new Error('Errors flushing docs. See log for details')) + } else { + callback(null) } + }) + }) +} - logger.log({ project_id, doc_ids }, 'deleting docs') - return async.series(jobs, () => - // When deleting the project here we want to ensure that project - // history is completely flushed because the project may be - // deleted in web after this call completes, and so further - // attempts to flush would fail after that. - HistoryManager.flushProjectChanges(project_id, options, function ( - error - ) { - if (errors.length > 0) { - return callback( - new Error('Errors deleting docs. See log for details') - ) - } else if (error != null) { - return callback(error) - } else { - return callback(null) +function flushAndDeleteProjectWithLocks(projectId, options, _callback) { + const timer = new Metrics.Timer( + 'projectManager.flushAndDeleteProjectWithLocks' + ) + const callback = function (...args) { + timer.done() + _callback(...args) + } + + RedisManager.getDocIdsInProject(projectId, (error, docIds) => { + if (error) { + return callback(error) + } + const errors = [] + const jobs = docIds.map((docId) => (callback) => { + DocumentManager.flushAndDeleteDocWithLock( + projectId, + docId, + {}, + (error) => { + if (error) { + logger.error({ err: error, projectId, docId }, 'error deleting doc') + errors.push(error) } - }) + callback() + } ) }) - }, - queueFlushAndDeleteProject(project_id, callback) { - if (callback == null) { - callback = function (error) {} + logger.log({ projectId, docIds }, 'deleting docs') + async.series(jobs, () => + // When deleting the project here we want to ensure that project + // history is completely flushed because the project may be + // deleted in web after this call completes, and so further + // attempts to flush would fail after that. + HistoryManager.flushProjectChanges(projectId, options, (error) => { + if (errors.length > 0) { + callback(new Error('Errors deleting docs. See log for details')) + } else if (error) { + callback(error) + } else { + callback(null) + } + }) + ) + }) +} + +function queueFlushAndDeleteProject(projectId, callback) { + RedisManager.queueFlushAndDeleteProject(projectId, (error) => { + if (error) { + logger.error( + { projectId, error }, + 'error adding project to flush and delete queue' + ) + return callback(error) } - return RedisManager.queueFlushAndDeleteProject(project_id, function ( - error - ) { - if (error != null) { + Metrics.inc('queued-delete') + callback() + }) +} + +function getProjectDocsTimestamps(projectId, callback) { + RedisManager.getDocIdsInProject(projectId, (error, docIds) => { + if (error) { + return callback(error) + } + if (docIds.length === 0) { + return callback(null, []) + } + RedisManager.getDocTimestamps(docIds, (error, timestamps) => { + if (error) { + return callback(error) + } + callback(null, timestamps) + }) + }) +} + +function getProjectDocsAndFlushIfOld( + projectId, + projectStateHash, + excludeVersions, + _callback +) { + const timer = new Metrics.Timer('projectManager.getProjectDocsAndFlushIfOld') + const callback = function (...args) { + timer.done() + _callback(...args) + } + + RedisManager.checkOrSetProjectState( + projectId, + projectStateHash, + (error, projectStateChanged) => { + if (error) { logger.error( - { project_id, error }, - 'error adding project to flush and delete queue' + { err: error, projectId }, + 'error getting/setting project state in getProjectDocsAndFlushIfOld' ) return callback(error) } - Metrics.inc('queued-delete') - return callback() - }) - }, - - getProjectDocsTimestamps(project_id, callback) { - if (callback == null) { - callback = function (error) {} - } - return RedisManager.getDocIdsInProject(project_id, function ( - error, - doc_ids - ) { - if (error != null) { - return callback(error) + // we can't return docs if project structure has changed + if (projectStateChanged) { + return callback( + Errors.ProjectStateChangedError('project state changed') + ) } - if (!(doc_ids != null ? doc_ids.length : undefined)) { - return callback(null, []) - } - return RedisManager.getDocTimestamps(doc_ids, function ( - error, - timestamps - ) { - if (error != null) { - return callback(error) - } - return callback(null, timestamps) - }) - }) - }, - - getProjectDocsAndFlushIfOld( - project_id, - projectStateHash, - excludeVersions, - _callback - ) { - if (excludeVersions == null) { - excludeVersions = {} - } - if (_callback == null) { - _callback = function (error, docs) {} - } - const timer = new Metrics.Timer( - 'projectManager.getProjectDocsAndFlushIfOld' - ) - const callback = function (...args) { - timer.done() - return _callback(...Array.from(args || [])) - } - - return RedisManager.checkOrSetProjectState( - project_id, - projectStateHash, - function (error, projectStateChanged) { - if (error != null) { + // project structure hasn't changed, return doc content from redis + RedisManager.getDocIdsInProject(projectId, (error, docIds) => { + if (error) { logger.error( - { err: error, project_id }, - 'error getting/setting project state in getProjectDocsAndFlushIfOld' + { err: error, projectId }, + 'error getting doc ids in getProjectDocs' ) return callback(error) } - // we can't return docs if project structure has changed - if (projectStateChanged) { - return callback( - Errors.ProjectStateChangedError('project state changed') + // get the doc lines from redis + const jobs = docIds.map((docId) => (cb) => { + DocumentManager.getDocAndFlushIfOldWithLock( + projectId, + docId, + (err, lines, version) => { + if (err) { + logger.error( + { err, projectId, docId }, + 'error getting project doc lines in getProjectDocsAndFlushIfOld' + ) + return cb(err) + } + const doc = { _id: docId, lines, v: version } // create a doc object to return + cb(null, doc) + } ) - } - // project structure hasn't changed, return doc content from redis - return RedisManager.getDocIdsInProject(project_id, function ( - error, - doc_ids - ) { - if (error != null) { - logger.error( - { err: error, project_id }, - 'error getting doc ids in getProjectDocs' - ) + }) + async.series(jobs, (error, docs) => { + if (error) { return callback(error) } - const jobs = [] - for (const doc_id of Array.from(doc_ids || [])) { - ;((doc_id) => - jobs.push(( - cb // get the doc lines from redis - ) => - DocumentManager.getDocAndFlushIfOldWithLock( - project_id, - doc_id, - function (err, lines, version) { - if (err != null) { - logger.error( - { err, project_id, doc_id }, - 'error getting project doc lines in getProjectDocsAndFlushIfOld' - ) - return cb(err) - } - const doc = { _id: doc_id, lines, v: version } // create a doc object to return - return cb(null, doc) - } - ) - ))(doc_id) - } - return async.series(jobs, function (error, docs) { - if (error != null) { - return callback(error) - } - return callback(null, docs) - }) + callback(null, docs) }) - } - ) - }, - - clearProjectState(project_id, callback) { - if (callback == null) { - callback = function (error) {} + }) } - return RedisManager.clearProjectState(project_id, callback) - }, + ) +} - updateProjectWithLocks( - project_id, - projectHistoryId, - user_id, - docUpdates, - fileUpdates, - version, - _callback - ) { - if (_callback == null) { - _callback = function (error) {} - } - const timer = new Metrics.Timer('projectManager.updateProject') - const callback = function (...args) { - timer.done() - return _callback(...Array.from(args || [])) - } +function clearProjectState(projectId, callback) { + RedisManager.clearProjectState(projectId, callback) +} - const project_version = version - let project_subversion = 0 // project versions can have multiple operations +function updateProjectWithLocks( + projectId, + projectHistoryId, + userId, + updates, + projectVersion, + _callback +) { + const timer = new Metrics.Timer('projectManager.updateProject') + const callback = function (...args) { + timer.done() + _callback(...args) + } - let project_ops_length = 0 + let projectSubversion = 0 // project versions can have multiple operations + let projectOpsLength = 0 - const handleDocUpdate = function (projectUpdate, cb) { - const doc_id = projectUpdate.id - projectUpdate.version = `${project_version}.${project_subversion++}` - if (projectUpdate.docLines != null) { - return ProjectHistoryRedisManager.queueAddEntity( - project_id, + function handleUpdate(update, cb) { + update.version = `${projectVersion}.${projectSubversion++}` + switch (update.type) { + case 'add-doc': + ProjectHistoryRedisManager.queueAddEntity( + projectId, projectHistoryId, 'doc', - doc_id, - user_id, - projectUpdate, - function (error, count) { - project_ops_length = count - return cb(error) + update.id, + userId, + update, + (error, count) => { + projectOpsLength = count + cb(error) } ) - } else { - return DocumentManager.renameDocWithLock( - project_id, - doc_id, - user_id, - projectUpdate, + break + case 'rename-doc': + DocumentManager.renameDocWithLock( + projectId, + update.id, + userId, + update, projectHistoryId, - function (error, count) { - project_ops_length = count - return cb(error) + (error, count) => { + projectOpsLength = count + cb(error) } ) - } - } - - const handleFileUpdate = function (projectUpdate, cb) { - const file_id = projectUpdate.id - projectUpdate.version = `${project_version}.${project_subversion++}` - if (projectUpdate.url != null) { - return ProjectHistoryRedisManager.queueAddEntity( - project_id, + break + case 'add-file': + ProjectHistoryRedisManager.queueAddEntity( + projectId, projectHistoryId, 'file', - file_id, - user_id, - projectUpdate, - function (error, count) { - project_ops_length = count - return cb(error) + update.id, + userId, + update, + (error, count) => { + projectOpsLength = count + cb(error) } ) - } else { - return ProjectHistoryRedisManager.queueRenameEntity( - project_id, + break + case 'rename-file': + ProjectHistoryRedisManager.queueRenameEntity( + projectId, projectHistoryId, 'file', - file_id, - user_id, - projectUpdate, - function (error, count) { - project_ops_length = count - return cb(error) + update.id, + userId, + update, + (error, count) => { + projectOpsLength = count + cb(error) } ) - } + break + default: + cb(new Error(`Unknown update type: ${update.type}`)) } - - return async.eachSeries(docUpdates, handleDocUpdate, function (error) { - if (error != null) { - return callback(error) - } - return async.eachSeries(fileUpdates, handleFileUpdate, function (error) { - if (error != null) { - return callback(error) - } - if ( - HistoryManager.shouldFlushHistoryOps( - project_ops_length, - docUpdates.length + fileUpdates.length, - HistoryManager.FLUSH_PROJECT_EVERY_N_OPS - ) - ) { - HistoryManager.flushProjectChangesAsync(project_id) - } - return callback() - }) - }) } + + async.eachSeries(updates, handleUpdate, (error) => { + if (error) { + return callback(error) + } + if ( + HistoryManager.shouldFlushHistoryOps( + projectOpsLength, + updates.length, + HistoryManager.FLUSH_PROJECT_EVERY_N_OPS + ) + ) { + HistoryManager.flushProjectChangesAsync(projectId) + } + callback() + }) } diff --git a/services/document-updater/package-lock.json b/services/document-updater/package-lock.json index e3d34fc959..6d838e6217 100644 --- a/services/document-updater/package-lock.json +++ b/services/document-updater/package-lock.json @@ -160,7 +160,7 @@ "@google-cloud/debug-agent": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@google-cloud/debug-agent/-/debug-agent-3.2.0.tgz", - "integrity": "sha512-fP87kYbS6aeDna08BivwQ1J260mwJGchRi99XdWCgqbRwuFac8ul0OT5i2wEeDSc5QaDX8ZuWQQ0igZvh1rTyQ==", + "integrity": "sha1-2qdjWhaYpWY31dxXzhED536uKdM=", "requires": { "@google-cloud/common": "^0.32.0", "@sindresorhus/is": "^0.15.0", @@ -393,7 +393,7 @@ "@google-cloud/profiler": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@google-cloud/profiler/-/profiler-0.2.3.tgz", - "integrity": "sha512-rNvtrFtIebIxZEJ/O0t8n7HciZGIXBo8DvHxWqAmsCaeLvkTtsaL6HmPkwxrNQ1IhbYWAxF+E/DwCiHyhKmgTg==", + "integrity": "sha1-Fj3738Mwuug1X+RuHlvgZTV7H1w=", "requires": { "@google-cloud/common": "^0.26.0", "@types/console-log-level": "^1.4.0", @@ -415,7 +415,7 @@ "@google-cloud/common": { "version": "0.26.2", "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-0.26.2.tgz", - "integrity": "sha512-xJ2M/q3MrUbnYZuFlpF01caAlEhAUoRn0NXp93Hn3pkFpfSOG8YfbKbpBAHvcKVbBOAKVIwPsleNtuyuabUwLQ==", + "integrity": "sha1-nFTiRxqEqgMelaJIJJduCA8lVkU=", "requires": { "@google-cloud/projectify": "^0.3.2", "@google-cloud/promisify": "^0.3.0", @@ -439,7 +439,7 @@ "@google-cloud/promisify": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-0.3.1.tgz", - "integrity": "sha512-QzB0/IMvB0eFxFK7Eqh+bfC8NLv3E9ScjWQrPOk6GgfNroxcVITdTlT8NRsRrcp5+QQJVPLkRqKG0PUdaWXmHw==" + "integrity": "sha1-9kHm2USo4KBe4MsQkd+mAIm+zbo=" }, "agent-base": { "version": "4.3.0", @@ -452,7 +452,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==" + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, "debug": { "version": "3.2.6", @@ -476,7 +476,7 @@ "gcp-metadata": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.9.3.tgz", - "integrity": "sha512-caV4S84xAjENtpezLCT/GILEAF5h/bC4cNqZFmt/tjTn8t+JBtTkQrgBrJu3857YdsnlM8rxX/PMcKGtE8hUlw==", + "integrity": "sha1-H510lfdGChRSZIHynhFZbdVj3SY=", "requires": { "gaxios": "^1.0.2", "json-bigint": "^0.3.0" @@ -485,7 +485,7 @@ "google-auth-library": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-2.0.2.tgz", - "integrity": "sha512-FURxmo1hBVmcfLauuMRKOPYAPKht3dGuI2wjeJFalDUThO0HoYVjr4yxt5cgYSFm1dgUpmN9G/poa7ceTFAIiA==", + "integrity": "sha1-ejFdIDZ0Svavyth7IQ7mY4tA9Xs=", "requires": { "axios": "^0.18.0", "gcp-metadata": "^0.7.0", @@ -499,7 +499,7 @@ "gcp-metadata": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-0.7.0.tgz", - "integrity": "sha512-ffjC09amcDWjh3VZdkDngIo7WoluyC5Ag9PAYxZbmQLOLNI8lvPtoKTSCyU54j2gwy5roZh6sSMTfkY2ct7K3g==", + "integrity": "sha1-bDXbtSvaMqQnu5yY9UI33dG1QG8=", "requires": { "axios": "^0.18.0", "extend": "^3.0.1", @@ -602,7 +602,7 @@ "@google-cloud/trace-agent": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@google-cloud/trace-agent/-/trace-agent-3.6.1.tgz", - "integrity": "sha512-KDo85aPN4gSxJ7oEIOlKd7aGENZFXAM1kbIn1Ds+61gh/K1CQWSyepgJo3nUpAwH6D1ezDWV7Iaf8ueoITc8Uw==", + "integrity": "sha1-W+dEE5TQ6ldY8o25IqUAT/PwO+w=", "requires": { "@google-cloud/common": "^0.32.1", "builtin-modules": "^3.0.0", @@ -829,27 +829,27 @@ "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" }, "@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha1-TIVzDlm5ofHzSQR9vyQpYDS7JzU=" }, "@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha1-fvN/DQEPsCitGtWXIuUG2SYoFcs=" }, "@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" }, "@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", "requires": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -858,32 +858,93 @@ "@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" }, "@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" }, "@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" }, "@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" }, "@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, "@sindresorhus/is": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.15.0.tgz", - "integrity": "sha512-lu8BpxjAtRCAo5ifytTpCPCj99LF7o/2Myn+NXyNCBqvPYn7Pjd76AMmUB5l7XF1U6t0hcWrlEM5ESufW7wAeA==" + "integrity": "sha1-lpFbqgXmpqHRN7rfSYTT/AWCC7Y=" + }, + "@sinonjs/commons": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.2.tgz", + "integrity": "sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + }, + "dependencies": { + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/formatio": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", + "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^5.0.2" + } + }, + "@sinonjs/samsam": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", + "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + }, + "dependencies": { + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true }, "@tootallnate/once": { "version": "1.0.0", @@ -893,7 +954,7 @@ "@types/caseless": { "version": "0.12.2", "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" + "integrity": "sha1-9l09Y4ngHutFi9VNyPUrlalGO8g=" }, "@types/color-name": { "version": "1.1.1", @@ -904,12 +965,12 @@ "@types/console-log-level": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@types/console-log-level/-/console-log-level-1.4.0.tgz", - "integrity": "sha512-x+OscEQwcx5Biair4enH7ov9W+clcqUWaZRaxn5IkT4yNWWjRr2oiYDkY/x1uXSTVZOQ2xlbFQySaQGB+VdXGQ==" + "integrity": "sha1-7/ccQa689RyLpa2LBdfVQkviuPM=" }, "@types/duplexify": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/@types/duplexify/-/duplexify-3.6.0.tgz", - "integrity": "sha512-5zOA53RUlzN74bvrSGwjudssD9F3a797sDZQkiYpUOxW+WHaXTCPz4/d5Dgi6FKnOqZ2CpaTo0DhgIfsXAOE/A==", + "integrity": "sha1-38grZL06IWj1vSZESvFlvwI33Ng=", "requires": { "@types/node": "*" } @@ -970,7 +1031,7 @@ "@types/semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" + "integrity": "sha1-FGwqKe59O65L8vyydGNuJkyBPEU=" }, "@types/tough-cookie": { "version": "2.3.6", @@ -1033,7 +1094,7 @@ "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "integrity": "sha1-6vVNU7YrrkE46AnKIlyEOabvs5I=", "requires": { "event-target-shim": "^5.0.0" } @@ -1182,7 +1243,7 @@ "arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + "integrity": "sha1-yWVekzHgq81YjSp8rX6ZVvZnAfo=" }, "asn1": { "version": "0.2.4", @@ -1200,7 +1261,7 @@ "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs=", "dev": true }, "ast-types-flow": { @@ -1226,7 +1287,7 @@ "async-listener": { "version": "0.6.10", "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz", - "integrity": "sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw==", + "integrity": "sha1-p8l6vlcLpgLXgic8DeYKUePhfLw=", "requires": { "semver": "^5.3.0", "shimmer": "^1.1.0" @@ -1242,12 +1303,12 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { "version": "1.9.1", @@ -1257,7 +1318,7 @@ "axios": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", - "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "integrity": "sha1-/z8N4ue10YDnV62YAA8Qgbh7zqM=", "requires": { "follow-redirects": "1.5.10", "is-buffer": "^2.0.2" @@ -1286,7 +1347,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base64-js": { "version": "1.3.1", @@ -1304,12 +1365,12 @@ "bignumber.js": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", - "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + "integrity": "sha1-gMBIdZ2CaACAfEv9Uh5Q7bulel8=" }, "bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=", "requires": { "file-uri-to-path": "1.0.0" } @@ -1317,7 +1378,7 @@ "bintrees": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz", - "integrity": "sha512-tbaUB1QpTIj4cKY8c1rvNAvEQXA+ekzHmbe4jzNfW3QWsF9GnnP/BRWyl6/qqS53heoYJ93naaFcm/jooONH8g==" + "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ=" }, "bl": { "version": "2.2.0", @@ -1379,7 +1440,7 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "integrity": "sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA=", "dev": true }, "bson": { @@ -1390,17 +1451,17 @@ "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, "builtin-modules": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + "integrity": "sha1-qtl8FRMet2tltQ7yCOdYTNdqdIQ=" }, "bunyan": { "version": "0.22.3", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-0.22.3.tgz", - "integrity": "sha512-v9dd5qmd6nJHEi7fiNo1fR2pMpE8AiB47Ap984p4iJKj+dEA69jSccmq6grFQn6pxIh0evvKpC5XO1SKfiaRoQ==", + "integrity": "sha1-ehncG0yMZF90AkGnQPIkUUfGfsI=", "requires": { "dtrace-provider": "0.2.8", "mv": "~2" @@ -1414,21 +1475,6 @@ } } }, - "buster-core": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/buster-core/-/buster-core-0.6.4.tgz", - "integrity": "sha512-WxitPqvzr2J7AA2eLEddv72XYaunQUDI0ICZhd1ucT/HhQI6JqfA7WQtoBoVZSgUn1+7uf9r7Plhh8PdO2+Kjg==", - "dev": true - }, - "buster-format": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/buster-format/-/buster-format-0.5.6.tgz", - "integrity": "sha512-AiH2uZZSwyhgtM7l8/A/7HaqUBJnXwcj9oUPIrSvTKTOo/Go0KJiqnGnRRl4zGqIf3IK3pC/KfkgJMgn6lpyzw==", - "dev": true, - "requires": { - "buster-core": "=0.6.4" - } - }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -1470,12 +1516,12 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chai": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha512-eRYY0vPS2a9zt5w5Z0aCeWbrXTEyvk7u/Xf71EzNObrjSCPgMm1Nku/D/u2tiqHBX5j40wWhj54YJLtgn8g55A==", + "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", "dev": true, "requires": { "assertion-error": "^1.0.1", @@ -1486,7 +1532,7 @@ "chai-spies": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-0.7.1.tgz", - "integrity": "sha512-ezo+u5DUDjPhOYkgsjbbVhtdzsnVr6n2CL/juJA89YnBsWO4ocL14Ake0txlGrGZo/HwcfhFGaV0czdunr3tHA==", + "integrity": "sha1-ND2Z9RJEIS6LF+ZLk5lv97LCqbE=", "dev": true }, "chalk": { @@ -1576,12 +1622,12 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "console-log-level": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/console-log-level/-/console-log-level-1.4.1.tgz", - "integrity": "sha512-VZzbIORbP+PPcN/gg3DXClTLPLg5Slwd5fL2MIc+o1qZ4BXBvWyc6QxPk6T/Mkr6IVjRpoAGf32XxP3ZWMVRcQ==" + "integrity": "sha1-nFprue8e9lsFq6gwKLD/iUzfYwo=" }, "contains-path": { "version": "0.1.0", @@ -1605,7 +1651,7 @@ "continuation-local-storage": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", - "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "integrity": "sha1-EfYT906RT+mzTJKtLSj+auHbf/s=", "requires": { "async-listener": "^0.6.0", "emitter-listener": "^1.1.1" @@ -1644,7 +1690,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "cp-file": { "version": "6.2.0", @@ -1697,7 +1743,7 @@ "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { "assert-plus": "^1.0.0" } @@ -1718,7 +1764,7 @@ "deep-eql": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha512-6sEotTRGBFiNcqVoeHwnfopbSpi5NbH1VWJmYCVkmxMmaVTT0bUTrNaGyBwhgP4MZL012W/mkzIn3Da+iDYweg==", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", "dev": true, "requires": { "type-detect": "0.1.1" @@ -1727,7 +1773,7 @@ "type-detect": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha512-5rqszGVwYgBoDkIm2oUtvkfZMQ0vk29iDMU0W2qCa3rG0vPDNczCMT4hV/bLBgLg8k8ri6+u3Zbt+S/14eMzlA==", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", "dev": true } } @@ -1758,7 +1804,7 @@ "delay": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/delay/-/delay-4.3.0.tgz", - "integrity": "sha512-Lwaf3zVFDMBop1yDuFZ19F9WyGcZcGacsbdlZtWjQmM50tOcMntm1njF/Nb/Vjij3KaSvCF+sEYGKrrjObu2NA==" + "integrity": "sha1-7+6/uPVFV5yzlrOnIkQ+yW0UxQ4=" }, "delayed-stream": { "version": "1.0.0", @@ -1768,7 +1814,7 @@ "denque": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + "integrity": "sha1-Z0T/dkHBSMP4ppwwflEjXB9KN88=" }, "depd": { "version": "1.1.2", @@ -1783,7 +1829,7 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "integrity": "sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI=", "dev": true }, "dlv": { @@ -1821,7 +1867,7 @@ "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "integrity": "sha1-Kk31MX9sz9kfhtb9JdjYoQO4gwk=", "requires": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", @@ -1861,7 +1907,7 @@ "each-series": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/each-series/-/each-series-1.0.0.tgz", - "integrity": "sha512-4MQloCGGCmT5GJZK5ibgJSvTK1c1QSrNlDvLk6fEyRxjZnXjl+NNFfzhfXpmnWh33Owc9D9klrdzCUi7yc9r4Q==" + "integrity": "sha1-+Ibmxm39sl7x/nNWQUbuXLR4r8s=" }, "ecc-jsbn": { "version": "0.1.2", @@ -1875,7 +1921,7 @@ "ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "integrity": "sha1-rg8PothQRe8UqBfao86azQSJ5b8=", "requires": { "safe-buffer": "^5.0.1" } @@ -1883,7 +1929,7 @@ "emitter-listener": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", - "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "integrity": "sha1-VrFA6PaZI3Wz18ssqxzHQy2WMug=", "requires": { "shimmer": "^1.2.0" } @@ -1909,7 +1955,7 @@ "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" }, "error-ex": { "version": "1.3.2", @@ -1957,12 +2003,12 @@ "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "integrity": "sha1-TrIVlMlyvEBVPSduUQU5FD21Pgo=" }, "es6-promisify": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "requires": { "es6-promise": "^4.0.3" } @@ -1975,7 +2021,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { "version": "6.6.0", @@ -2565,7 +2611,7 @@ "event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + "integrity": "sha1-XU0+vflYPWOlMzzi3rdICrKwV4k=" }, "eventid": { "version": "1.0.0", @@ -2632,7 +2678,7 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "fast-deep-equal": { "version": "3.1.1", @@ -2659,7 +2705,7 @@ "fast-text-encoding": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz", - "integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ==" + "integrity": "sha1-PlzoKTQJz6pxd6cbnKhOGx5vJe8=" }, "figures": { "version": "3.2.0", @@ -2682,7 +2728,7 @@ "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=" }, "finalhandler": { "version": "1.1.2", @@ -2719,7 +2765,7 @@ "findit2": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", - "integrity": "sha512-lg/Moejf4qXovVutL0Lz4IsaPoNYMuxt4PA0nGqFxnJ1CTTGGlEO2wKgoDpwknhvZ8k4Q2F+eesgkLbG2Mxfog==" + "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=" }, "flat-cache": { "version": "2.0.1", @@ -2766,7 +2812,7 @@ "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=", "requires": { "debug": "=3.1.0" }, @@ -2828,7 +2874,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "function-bind": { "version": "1.1.1", @@ -2877,7 +2923,7 @@ "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { "assert-plus": "^1.0.0" } @@ -2885,7 +2931,7 @@ "glob": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "optional": true, "requires": { "inflight": "^1.0.4", @@ -3009,7 +3055,7 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { "version": "5.1.3", @@ -3075,13 +3121,13 @@ "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha512-z/GDPjlRMNOa2XJiB4em8wJpuuBfrFOlYKTZxtpkdr1uPdibHI8rYA3MY0KDObpVyaes0e/aunid/t88ZI2EKA==", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, "hex2dec": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/hex2dec/-/hex2dec-1.1.2.tgz", - "integrity": "sha512-Yu+q/XWr2fFQ11tHxPq4p4EiNkb2y+lAacJNhAdRXVfRIcDH6gi7htWFnnlIzvqHMHoWeIsfXlNAjZInpAOJDA==" + "integrity": "sha1-jhzkvvNqdPfVcjw/swkMKGAHczg=" }, "hosted-git-info": { "version": "2.8.8", @@ -3217,7 +3263,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3389,7 +3435,7 @@ "is": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", - "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==" + "integrity": "sha1-Yc/23TxBk9uUo9YlggcrROVkXXk=" }, "is-arrayish": { "version": "0.2.1", @@ -3475,7 +3521,7 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "isarray": { "version": "1.0.0", @@ -3490,7 +3536,7 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-lib-coverage": { "version": "2.0.5", @@ -3612,7 +3658,7 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jsesc": { "version": "2.5.2", @@ -3622,7 +3668,7 @@ "json-bigint": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-0.3.0.tgz", - "integrity": "sha512-u+c/u/F+JNPUekHCFyGVycRPyh9UHD5iUhSyIAn10kxbDTJxijwAbT6XHaONEOXuGGfmWUSroheXgHcml4gLgg==", + "integrity": "sha1-DM2RLEuCcNBfBW+9E4FLU9OCWx4=", "requires": { "bignumber.js": "^7.0.0" } @@ -3635,7 +3681,7 @@ "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha512-a3xHnILGMtk+hDOqNwHzF6e2fNbiMrXZvxKQiEv2MlgQP+pjIOzqAmKYD2mDpXYE/44M7g+n9p2bKkYWDUcXCQ==" + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { "version": "0.4.1", @@ -3651,12 +3697,12 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha512-4Dj8Rf+fQ+/Pn7C5qeEX02op1WfOss3PKTE9Nsop3Dx+6UPxlm1dr/og7o2cRa5hNN07CACr4NFzRLtj/rjWog==", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -3674,6 +3720,12 @@ "object.assign": "^4.1.0" } }, + "just-extend": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", + "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", + "dev": true + }, "jwa": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", @@ -3748,18 +3800,24 @@ "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=" }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.has": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz", @@ -3780,7 +3838,7 @@ "lodash.pickby": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", - "integrity": "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q==" + "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=" }, "lodash.unescape": { "version": "4.0.1", @@ -3912,7 +3970,7 @@ "long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=" }, "loose-envify": { "version": "1.4.0", @@ -3926,7 +3984,7 @@ "lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "integrity": "sha1-HaJ+ZxAnGUdpXa9oSOhH8B2EuSA=", "requires": { "yallist": "^3.0.2" } @@ -3934,7 +3992,7 @@ "lsmod": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lsmod/-/lsmod-1.0.0.tgz", - "integrity": "sha512-Y+6V75r+mGWzWEPr9h6PFmStielICu5JBHLUg18jCsD2VFmEfgHbq/EgnY4inElsUD9eKL9id1qp34w46rSIKQ==" + "integrity": "sha1-mgD3bco26yP6BTUK/htYXUKZ5ks=" }, "lynx": { "version": "0.1.1", @@ -4011,7 +4069,7 @@ "mersenne": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/mersenne/-/mersenne-0.0.4.tgz", - "integrity": "sha512-XoSUL+nF8hMTKGQxUs8r3Btdsf1yuKKBdCCGbh3YXgCXuVKishpZv1CNc385w9s8t4Ynwc5h61BwW/FCVulkbg==" + "integrity": "sha1-QB/ex+whzbngPNPTAhOY2iGycIU=" }, "messageformat": { "version": "2.3.0", @@ -4090,7 +4148,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "requires": { "brace-expansion": "^1.1.7" } @@ -4098,17 +4156,17 @@ "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha512-8OCq0De/h9ZxseqzCH8Kw/Filf5pF/vMI6+BH7Lu0jXz2pqYCjTAQRolSxRIi+Ax+oCCjlxoJMP0YQ4XlrQNHg==" + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=" }, "mocha": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "integrity": "sha1-bYrlCPWRZ/lA8rWzxKYSrlDJCuY=", "dev": true, "requires": { "browser-stdout": "1.3.1", @@ -4127,7 +4185,7 @@ "commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "integrity": "sha1-30boZ9D8Kuxmo0ZitAapzK//Ww8=", "dev": true }, "debug": { @@ -4142,7 +4200,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -4156,7 +4214,7 @@ "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { "minimist": "0.0.8" @@ -4173,12 +4231,12 @@ "module-details-from-path": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", - "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==" + "integrity": "sha1-EUyUlnPiqKNenTV4hSeqN7Z52is=" }, "moment": { "version": "2.24.0", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", - "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", + "integrity": "sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s=", "optional": true }, "mongodb": { @@ -4223,7 +4281,7 @@ "mv": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", - "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", "optional": true, "requires": { "mkdirp": "~0.5.1", @@ -4234,7 +4292,7 @@ "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "optional": true, "requires": { "minimist": "0.0.8" @@ -4256,7 +4314,7 @@ "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", - "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "optional": true }, "negotiator": { @@ -4275,10 +4333,40 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "nise": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", + "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + } + } + }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "integrity": "sha1-5jNFY4bUqlWGP2dqerDaqP3ssP0=" }, "node-forge": { "version": "0.9.1", @@ -4452,7 +4540,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } @@ -4510,7 +4598,7 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=" }, "package-hash": { "version": "3.0.0", @@ -4549,12 +4637,12 @@ "parse-mongo-url": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/parse-mongo-url/-/parse-mongo-url-1.1.1.tgz", - "integrity": "sha512-7bZUusQIrFLwvsLHBnCz2WKYQ5LKO/LwKPnvQxbMIh9gDx8H5ZsknRmLjZdn6GVdrgVOwqDrZKsY0qDLNmRgcw==" + "integrity": "sha1-ZiON9fjnwMjKTNlw1KtqE3PrdbU=" }, "parse-ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", - "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==" + "integrity": "sha1-NIVlp1PUOR+lJAKZVrFyy3dTCX0=" }, "parseurl": { "version": "1.3.3", @@ -4569,7 +4657,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-is-inside": { "version": "1.0.2", @@ -4586,7 +4674,7 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=" }, "path-to-regexp": { "version": "0.1.7", @@ -4611,12 +4699,12 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + "integrity": "sha1-SyzSXFDVmHNcUCkiJP2MbfQeMjE=" }, "pkg-dir": { "version": "3.0.0", @@ -5282,7 +5370,7 @@ "pretty-ms": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-4.0.0.tgz", - "integrity": "sha512-qG66ahoLCwpLXD09ZPHSCbUWYTqdosB7SMP4OffgTgL2PBKXMuUsrk5Bwg8q4qPkjTXsKBMr+YK3Ltd/6F9s/Q==", + "integrity": "sha1-Mbr0G5T9AiJwmKqgO9YmCOsNbpI=", "requires": { "parse-ms": "^2.0.0" } @@ -5320,7 +5408,7 @@ "protobufjs": { "version": "6.8.8", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.8.8.tgz", - "integrity": "sha512-AAmHtD5pXgZfi7GMpllpO3q1Xw1OYldr+dMUlAnffGTAhqkg72WdmSY71uKBF/JuyiKs8psYbtKrhi0ASCD8qw==", + "integrity": "sha1-yLTxKC/XqQ5vWxCe0RyEr4KQjnw=", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -5396,7 +5484,7 @@ "q": { "version": "0.9.2", "resolved": "https://registry.npmjs.org/q/-/q-0.9.2.tgz", - "integrity": "sha512-ZOxMuWPMJnsUdYhuQ9glpZwKhB4cm8ubYFy1nNCY8TkSAuZun5fd8jCDTlf2ykWnK8x9HGn1stNtLeG179DebQ==" + "integrity": "sha1-I8BsRsgTKGFqrhaNPuI6Vr1D2vY=" }, "qs": { "version": "6.7.0", @@ -5423,7 +5511,7 @@ "raven": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/raven/-/raven-1.1.3.tgz", - "integrity": "sha512-RYov4wAaflZasWiCrZuizd3jNXxCOkW1WrXgWsGVb8kRpdHNZ+vPY27R6RhVtqzWp+DG9a5l6iP0QUPK4EgzaQ==", + "integrity": "sha1-QnPBrm005CMPUbLAEEGjK5Iygio=", "requires": { "cookie": "0.3.1", "json-stringify-safe": "5.0.1", @@ -5435,7 +5523,7 @@ "cookie": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw==" + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" }, "uuid": { "version": "3.0.0", @@ -5493,22 +5581,22 @@ "redis": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/redis/-/redis-0.11.0.tgz", - "integrity": "sha512-wkgzIZ9HuxJ6Sul1IW/6FG13Ecv6q8kmdHb5xo09Hu6bgWzz5qsnM06SVMpDxFNbyApaRjy8CwnmVaRMMhAMWg==" + "integrity": "sha1-/cAdSrTL5LO7LLKByP5WnDhX9XE=" }, "redis-commands": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", - "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" + "integrity": "sha1-gNLiBpj+aI8icSf/nlFkp90X54U=" }, "redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==" + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" }, "redis-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", "requires": { "redis-errors": "^1.0.0" } @@ -5516,7 +5604,7 @@ "redis-sentinel": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/redis-sentinel/-/redis-sentinel-0.1.1.tgz", - "integrity": "sha512-cKtLSUzDsKmsB50J1eIV/SH11DSMiHgsm/gDPRCU5lXz5OyTSuLKWg9oc8d5n74kZwtAyRkfJP0x8vYXvlPjFQ==", + "integrity": "sha1-Vj3TQduZMgMfSX+v3Td+hkj/s+U=", "requires": { "q": "0.9.2", "redis": "0.11.x" @@ -5673,7 +5761,7 @@ "require-like": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", - "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "integrity": "sha1-rW8wwTvs15cBDEaK+ndcDAprR/o=", "dev": true }, "require-main-filename": { @@ -5690,7 +5778,7 @@ "require_optional": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", - "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "integrity": "sha1-TPNaQkf2TKPfjC7yCMxJSxyo/C4=", "requires": { "resolve-from": "^2.0.0", "semver": "^5.1.0" @@ -5714,7 +5802,7 @@ "resolve-from": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ==" + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" }, "restore-cursor": { "version": "3.1.0", @@ -5729,7 +5817,7 @@ "retry-axios": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/retry-axios/-/retry-axios-0.3.2.tgz", - "integrity": "sha512-jp4YlI0qyDFfXiXGhkCOliBN1G7fRH03Nqy8YdShzGqbY5/9S2x/IR6C88ls2DFkbWuL3ASkP7QD3pVrNpPgwQ==" + "integrity": "sha1-V1fID1hbTMTEmGqi/9R6YMbTXhM=" }, "retry-request": { "version": "4.1.1", @@ -5758,7 +5846,7 @@ "rimraf": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", - "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", "optional": true, "requires": { "glob": "^6.0.1" @@ -5787,7 +5875,7 @@ "safe-json-stringify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", - "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "integrity": "sha1-NW5EvJjx+TzkXfFLzXwBzahuCv0=", "optional": true }, "safer-buffer": { @@ -5798,7 +5886,7 @@ "sandboxed-module": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/sandboxed-module/-/sandboxed-module-0.2.2.tgz", - "integrity": "sha512-1QAd90eCdAnqVn2sLkRCCeFphH/TKLfoTcdyI6h9h2E+YEY+aKovggwzWWWi5IMObafl0W1wr+dQ5F6LFmjpzA==", + "integrity": "sha1-bL3sghOAx31FdcjIeDi5ET5kulA=", "dev": true, "requires": { "require-like": "0.1.2", @@ -5808,7 +5896,7 @@ "stack-trace": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.6.tgz", - "integrity": "sha512-5/6uZt7RYjjAl8z2j1mXWAewz+I4Hk2/L/3n6NRLIQ31+uQ7nMd9O6G69QCdrrufHv0QGRRHl/jwUEGTqhelTA==", + "integrity": "sha1-HnGb1qJin/CcGJ4Xqe+QKpT8XbA=", "dev": true } } @@ -5878,7 +5966,7 @@ "settings-sharelatex": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/settings-sharelatex/-/settings-sharelatex-1.1.0.tgz", - "integrity": "sha512-f7D+0lnlohoteSn6IKTH72NE+JnAdMWTKwQglAuimZWTID2FRRItZSGeYMTRpvEnaQApkoVwRp//WRMsiddnqw==", + "integrity": "sha1-Tv4vUpPbjxwVlnEEx5BfqHD/mS0=", "requires": { "coffee-script": "1.6.0" }, @@ -5886,7 +5974,7 @@ "coffee-script": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.6.0.tgz", - "integrity": "sha512-Tx8itEfCsQp8RbLDFt7qwjqXycAx2g6SI7//4PPUR2j6meLmNifYm6zKrNDcU1+Q/GWRhjhEZk7DaLG1TfIzGA==" + "integrity": "sha1-gIs5bhEPU9AhoZpO8fZb4OjjX6M=" } } }, @@ -5908,7 +5996,7 @@ "shimmer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", - "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + "integrity": "sha1-YQhZ994ye1h+/r9QH7QxF/mv8zc=" }, "side-channel": { "version": "1.0.2", @@ -5926,12 +6014,41 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sinon": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.5.2.tgz", - "integrity": "sha512-4I5YC02+PBQpCCPUydFuUpH4X4+t4IpFmKbP1gHthoFiD7yyLPx179im5jgUPw/O2BytFYnl6NLL4ijh585uiA==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", + "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", "dev": true, "requires": { - "buster-format": "~0.5" + "@sinonjs/commons": "^1.7.2", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/formatio": "^5.0.1", + "@sinonjs/samsam": "^5.0.3", + "diff": "^4.0.2", + "nise": "^4.0.1", + "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "slice-ansi": { @@ -5957,7 +6074,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" }, "sparse-bitfield": { "version": "3.0.3", @@ -6048,7 +6165,7 @@ "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=", "requires": { "through": "2" } @@ -6077,17 +6194,17 @@ "stack-trace": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.9.tgz", - "integrity": "sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==" + "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=" }, "standard-as-callback": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.0.1.tgz", - "integrity": "sha512-NQOxSeB8gOI5WjSaxjBgog2QFw55FV8TkS6Y07BiB3VJ8xNTvUYm0wl0s8ObgQ5NhdpnNfigMIKjgPESzgr4tg==" + "integrity": "sha1-7YuyVkjhWDF1m2Ajvbh+a2CzgSY=" }, "statsd-parser": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/statsd-parser/-/statsd-parser-0.0.4.tgz", - "integrity": "sha512-7XO+ur89EalMXXFQaydsczB8sclr5nDsNIoUu0IzJx1pIbHUhO3LtpSzBwetIuU9DyTLMiVaJBMtWS/Nb2KR4g==" + "integrity": "sha1-y9JDlTzELv/VSLXSI4jtaJ7GOb0=" }, "statuses": { "version": "1.5.0", @@ -6228,7 +6345,7 @@ "tdigest": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", - "integrity": "sha512-CXcDY/NIgIbKZPx5H4JJNpq6JwJhU5Z4+yWj4ZghDc7/9nVajiRlPPyMXRePPPlBfcayUqtoCXjo7/Hm82ecUA==", + "integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=", "requires": { "bintrees": "1.0.1" } @@ -6287,7 +6404,7 @@ "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { "version": "3.0.1", @@ -6350,7 +6467,7 @@ "to-mongodb-core": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-mongodb-core/-/to-mongodb-core-2.0.0.tgz", - "integrity": "sha512-vfXXcGYFP8+0L5IPOtUzzVIvPE/G3GN0TKa/PRBlzPqYyhm+UxhPmvv634EQgO4Ot8dHbBFihOslMJQclY8Z9A==" + "integrity": "sha1-NZbsdhOsmtO5ioncua77pWnNJ+s=" }, "to-no-case": { "version": "1.0.2", @@ -6411,7 +6528,7 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { "version": "0.3.2", @@ -6451,7 +6568,7 @@ "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha512-z4o1fvKUojIWh9XuaVLUDdf86RQiq13AC1dmHbTpoyuu+bquHms76v16CjycCbec87J7z0k//SiQVk0sMdFmpQ==" + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, "unpipe": { "version": "1.0.0", @@ -6461,7 +6578,7 @@ "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "integrity": "sha1-lMVA4f93KVbiKZUHwBCupsiDjrA=", "requires": { "punycode": "^2.1.0" } @@ -6469,7 +6586,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", @@ -6504,7 +6621,7 @@ "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -6593,7 +6710,7 @@ "when": { "version": "3.7.8", "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha512-5cZ7mecD3eYcMiCH4wtRPA5iFJZ50BJYDfckI5RRpQiktMiYTcn0ccLTZOvcbBume+1304fQztxeNzNS9Gvrnw==" + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=" }, "which": { "version": "1.3.1", @@ -6627,7 +6744,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "1.0.3", diff --git a/services/document-updater/package.json b/services/document-updater/package.json index af5f3ff6ac..3f0b1e2de0 100644 --- a/services/document-updater/package.json +++ b/services/document-updater/package.json @@ -55,7 +55,7 @@ "prettier": "^2.0.5", "prettier-eslint-cli": "^5.0.0", "sandboxed-module": "~0.2.0", - "sinon": "~1.5.2", + "sinon": "^9.0.2", "timekeeper": "^2.0.0" } } diff --git a/services/document-updater/test/acceptance/js/FlushingDocsTests.js b/services/document-updater/test/acceptance/js/FlushingDocsTests.js index 5556870f8e..109f89d434 100644 --- a/services/document-updater/test/acceptance/js/FlushingDocsTests.js +++ b/services/document-updater/test/acceptance/js/FlushingDocsTests.js @@ -121,26 +121,26 @@ describe('Flushing a doc to Mongo', function () { version: this.version }) let t = 30000 - sinon.stub( - MockWebApi, - 'setDocument', - ( - project_id, - doc_id, - lines, - version, - ranges, - lastUpdatedAt, - lastUpdatedBy, - callback - ) => { - if (callback == null) { - callback = function (error) {} + sinon + .stub(MockWebApi, 'setDocument') + .callsFake( + ( + project_id, + doc_id, + lines, + version, + ranges, + lastUpdatedAt, + lastUpdatedBy, + callback + ) => { + if (callback == null) { + callback = function (error) {} + } + setTimeout(callback, t) + return (t = 0) } - setTimeout(callback, t) - return (t = 0) - } - ) + ) return DocUpdaterClient.preloadDoc(this.project_id, this.doc_id, done) }) diff --git a/services/document-updater/test/acceptance/js/GettingADocumentTests.js b/services/document-updater/test/acceptance/js/GettingADocumentTests.js index fc97c8d825..a0b9de5773 100644 --- a/services/document-updater/test/acceptance/js/GettingADocumentTests.js +++ b/services/document-updater/test/acceptance/js/GettingADocumentTests.js @@ -216,12 +216,14 @@ describe('Getting a document', function () { DocUpdaterClient.randomId(), DocUpdaterClient.randomId() ]) - sinon.stub(MockWebApi, 'getDocument', (project_id, doc_id, callback) => { - if (callback == null) { - callback = function (error, doc) {} - } - return callback(new Error('oops')) - }) + sinon + .stub(MockWebApi, 'getDocument') + .callsFake((project_id, doc_id, callback) => { + if (callback == null) { + callback = function (error, doc) {} + } + return callback(new Error('oops')) + }) return DocUpdaterClient.getDoc( this.project_id, this.doc_id, @@ -248,12 +250,14 @@ describe('Getting a document', function () { DocUpdaterClient.randomId(), DocUpdaterClient.randomId() ]) - sinon.stub(MockWebApi, 'getDocument', (project_id, doc_id, callback) => { - if (callback == null) { - callback = function (error, doc) {} - } - return setTimeout(callback, 30000) - }) + sinon + .stub(MockWebApi, 'getDocument') + .callsFake((project_id, doc_id, callback) => { + if (callback == null) { + callback = function (error, doc) {} + } + return setTimeout(callback, 30000) + }) return done() }) diff --git a/services/document-updater/test/acceptance/js/SettingADocumentTests.js b/services/document-updater/test/acceptance/js/SettingADocumentTests.js index 484d51b57c..54ca9d00d0 100644 --- a/services/document-updater/test/acceptance/js/SettingADocumentTests.js +++ b/services/document-updater/test/acceptance/js/SettingADocumentTests.js @@ -88,9 +88,9 @@ describe('Setting a document', function () { }) after(function () { - MockTrackChangesApi.flushDoc.reset() - MockProjectHistoryApi.flushProject.reset() - MockWebApi.setDocument.reset() + MockTrackChangesApi.flushDoc.resetHistory() + MockProjectHistoryApi.flushProject.resetHistory() + MockWebApi.setDocument.resetHistory() }) it('should return a 204 status code', function () { @@ -171,9 +171,9 @@ describe('Setting a document', function () { }) after(function () { - MockTrackChangesApi.flushDoc.reset() - MockProjectHistoryApi.flushProject.reset() - MockWebApi.setDocument.reset() + MockTrackChangesApi.flushDoc.resetHistory() + MockProjectHistoryApi.flushProject.resetHistory() + MockWebApi.setDocument.resetHistory() }) it('should return a 204 status code', function () { @@ -254,9 +254,9 @@ describe('Setting a document', function () { }) after(function () { - MockTrackChangesApi.flushDoc.reset() - MockProjectHistoryApi.flushProject.reset() - MockWebApi.setDocument.reset() + MockTrackChangesApi.flushDoc.resetHistory() + MockProjectHistoryApi.flushProject.resetHistory() + MockWebApi.setDocument.resetHistory() }) it(`should return a ${testCase.expectedStatusCode} status code`, function () { @@ -310,9 +310,9 @@ describe('Setting a document', function () { }) after(function () { - MockTrackChangesApi.flushDoc.reset() - MockProjectHistoryApi.flushProject.reset() - MockWebApi.setDocument.reset() + MockTrackChangesApi.flushDoc.resetHistory() + MockProjectHistoryApi.flushProject.resetHistory() + MockWebApi.setDocument.resetHistory() }) it('should return a 204 status code', function () { @@ -388,9 +388,9 @@ describe('Setting a document', function () { }) after(function () { - MockTrackChangesApi.flushDoc.reset() - MockProjectHistoryApi.flushProject.reset() - MockWebApi.setDocument.reset() + MockTrackChangesApi.flushDoc.resetHistory() + MockProjectHistoryApi.flushProject.resetHistory() + MockWebApi.setDocument.resetHistory() }) it('should undo the tracked changes', function (done) { @@ -451,9 +451,9 @@ describe('Setting a document', function () { }) after(function () { - MockTrackChangesApi.flushDoc.reset() - MockProjectHistoryApi.flushProject.reset() - MockWebApi.setDocument.reset() + MockTrackChangesApi.flushDoc.resetHistory() + MockProjectHistoryApi.flushProject.resetHistory() + MockWebApi.setDocument.resetHistory() }) it('should not undo the tracked changes', function (done) { diff --git a/services/document-updater/test/unit/js/DocumentManager/DocumentManagerTests.js b/services/document-updater/test/unit/js/DocumentManager/DocumentManagerTests.js index 4baa5cee8d..295a643cee 100644 --- a/services/document-updater/test/unit/js/DocumentManager/DocumentManagerTests.js +++ b/services/document-updater/test/unit/js/DocumentManager/DocumentManagerTests.js @@ -52,7 +52,8 @@ describe('DocumentManager', function () { './RealTimeRedisManager': (this.RealTimeRedisManager = {}), './DiffCodec': (this.DiffCodec = {}), './UpdateManager': (this.UpdateManager = {}), - './RangesManager': (this.RangesManager = {}) + './RangesManager': (this.RangesManager = {}), + './Errors': Errors } }) this.project_id = 'project-id-123' @@ -765,10 +766,9 @@ describe('DocumentManager', function () { }) return it('should call the callback with a not found error', function () { - const error = new Errors.NotFoundError( - `document not found: ${this.doc_id}` - ) - return this.callback.calledWith(error).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) + .should.equal(true) }) }) }) @@ -848,10 +848,9 @@ describe('DocumentManager', function () { }) return it('should call the callback with a not found error', function () { - const error = new Errors.NotFoundError( - `document not found: ${this.doc_id}` - ) - return this.callback.calledWith(error).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) + .should.equal(true) }) }) }) diff --git a/services/document-updater/test/unit/js/HistoryRedisManager/HistoryRedisManagerTests.js b/services/document-updater/test/unit/js/HistoryRedisManager/HistoryRedisManagerTests.js index 68321533b3..c578a6be22 100644 --- a/services/document-updater/test/unit/js/HistoryRedisManager/HistoryRedisManagerTests.js +++ b/services/document-updater/test/unit/js/HistoryRedisManager/HistoryRedisManagerTests.js @@ -95,7 +95,7 @@ describe('HistoryRedisManager', function () { return it('should call the callback with an error', function () { return this.callback - .calledWith(new Error('cannot push no ops')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) diff --git a/services/document-updater/test/unit/js/HttpController/HttpControllerTests.js b/services/document-updater/test/unit/js/HttpController/HttpControllerTests.js index 64751e55db..4d9790926a 100644 --- a/services/document-updater/test/unit/js/HttpController/HttpControllerTests.js +++ b/services/document-updater/test/unit/js/HttpController/HttpControllerTests.js @@ -159,7 +159,7 @@ describe('HttpController', function () { it('should call next with NotFoundError', function () { this.next - .calledWith(new Errors.NotFoundError('not found')) + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) .should.equal(true) }) }) @@ -173,7 +173,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -252,7 +252,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) @@ -327,7 +327,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -387,7 +387,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -477,7 +477,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -550,7 +550,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -640,7 +640,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -703,7 +703,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -804,17 +804,39 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) - describe('updateProject', function () { + describe('updateProject (split doc and file updates)', function () { beforeEach(function () { this.projectHistoryId = 'history-id-123' this.userId = 'user-id-123' - this.docUpdates = sinon.stub() - this.fileUpdates = sinon.stub() + this.docUpdates = [ + { id: 1, pathname: 'thesis.tex', newPathname: 'book.tex' }, + { id: 2, pathname: 'article.tex', docLines: 'hello' } + ] + this.fileUpdates = [ + { id: 3, pathname: 'apple.png', newPathname: 'banana.png' }, + { id: 4, url: 'filestore.example.com/4' } + ] + this.expectedUpdates = [ + { + type: 'rename-doc', + id: 1, + pathname: 'thesis.tex', + newPathname: 'book.tex' + }, + { type: 'add-doc', id: 2, pathname: 'article.tex', docLines: 'hello' }, + { + type: 'rename-file', + id: 3, + pathname: 'apple.png', + newPathname: 'banana.png' + }, + { type: 'add-file', id: 4, url: 'filestore.example.com/4' } + ] this.version = 1234567 this.req = { query: {}, @@ -833,9 +855,7 @@ describe('HttpController', function () { describe('successfully', function () { beforeEach(function () { - this.ProjectManager.updateProjectWithLocks = sinon - .stub() - .callsArgWith(6) + this.ProjectManager.updateProjectWithLocks = sinon.stub().yields() this.HttpController.updateProject(this.req, this.res, this.next) }) @@ -845,8 +865,7 @@ describe('HttpController', function () { this.project_id, this.projectHistoryId, this.userId, - this.docUpdates, - this.fileUpdates, + this.expectedUpdates, this.version ) .should.equal(true) @@ -865,12 +884,88 @@ describe('HttpController', function () { beforeEach(function () { this.ProjectManager.updateProjectWithLocks = sinon .stub() - .callsArgWith(6, new Error('oops')) + .yields(new Error('oops')) this.HttpController.updateProject(this.req, this.res, this.next) }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) + }) + }) + }) + + describe('updateProject (single updates parameter)', function () { + beforeEach(function () { + this.projectHistoryId = 'history-id-123' + this.userId = 'user-id-123' + this.updates = [ + { + type: 'rename-doc', + id: 1, + pathname: 'thesis.tex', + newPathname: 'book.tex' + }, + { type: 'add-doc', id: 2, pathname: 'article.tex', docLines: 'hello' }, + { + type: 'rename-file', + id: 3, + pathname: 'apple.png', + newPathname: 'banana.png' + }, + { type: 'add-file', id: 4, url: 'filestore.example.com/4' } + ] + this.version = 1234567 + this.req = { + query: {}, + body: { + projectHistoryId: this.projectHistoryId, + userId: this.userId, + updates: this.updates, + version: this.version + }, + params: { + project_id: this.project_id + } + } + }) + + describe('successfully', function () { + beforeEach(function () { + this.ProjectManager.updateProjectWithLocks = sinon.stub().yields() + this.HttpController.updateProject(this.req, this.res, this.next) + }) + + it('should accept the change', function () { + this.ProjectManager.updateProjectWithLocks + .calledWith( + this.project_id, + this.projectHistoryId, + this.userId, + this.updates, + this.version + ) + .should.equal(true) + }) + + it('should return a successful No Content response', function () { + this.res.sendStatus.calledWith(204).should.equal(true) + }) + + it('should time the request', function () { + this.Metrics.Timer.prototype.done.called.should.equal(true) + }) + }) + + describe('when an errors occurs', function () { + beforeEach(function () { + this.ProjectManager.updateProjectWithLocks = sinon + .stub() + .yields(new Error('oops')) + this.HttpController.updateProject(this.req, this.res, this.next) + }) + + it('should call next with the error', function () { + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) @@ -925,7 +1020,7 @@ describe('HttpController', function () { }) it('should call next with the error', function () { - this.next.calledWith(new Error('oops')).should.equal(true) + this.next.calledWith(sinon.match.instanceOf(Error)).should.equal(true) }) }) }) diff --git a/services/document-updater/test/unit/js/LockManager/ReleasingTheLock.js b/services/document-updater/test/unit/js/LockManager/ReleasingTheLock.js index d0c88940cc..82b0bc7da7 100644 --- a/services/document-updater/test/unit/js/LockManager/ReleasingTheLock.js +++ b/services/document-updater/test/unit/js/LockManager/ReleasingTheLock.js @@ -92,7 +92,7 @@ describe('LockManager - releasing the lock', function () { return it('should return an error if the lock has expired', function () { return this.callback - .calledWith(new Error('tried to release timed out lock')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) diff --git a/services/document-updater/test/unit/js/LockManager/getLockTests.js b/services/document-updater/test/unit/js/LockManager/getLockTests.js index 1c41f2b0b4..cbe805040b 100644 --- a/services/document-updater/test/unit/js/LockManager/getLockTests.js +++ b/services/document-updater/test/unit/js/LockManager/getLockTests.js @@ -119,9 +119,13 @@ describe('LockManager - getting the lock', function () { }) return it('should return the callback with an error', function () { - const e = new Error('Timeout') - e.doc_id = this.doc_id - return this.callback.calledWith(e).should.equal(true) + return this.callback + .calledWith( + sinon.match + .instanceOf(Error) + .and(sinon.match.has('doc_id', this.doc_id)) + ) + .should.equal(true) }) }) }) diff --git a/services/document-updater/test/unit/js/LockManager/tryLockTests.js b/services/document-updater/test/unit/js/LockManager/tryLockTests.js index 77aecd87d1..36be6321bd 100644 --- a/services/document-updater/test/unit/js/LockManager/tryLockTests.js +++ b/services/document-updater/test/unit/js/LockManager/tryLockTests.js @@ -142,8 +142,9 @@ describe('LockManager - trying the lock', function () { }) return it('should return the callback with an error', function () { - const e = new Error('tried to release timed out lock') - return this.callback.calledWith(e).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Error)) + .should.equal(true) }) }) }) diff --git a/services/document-updater/test/unit/js/PersistenceManager/PersistenceManagerTests.js b/services/document-updater/test/unit/js/PersistenceManager/PersistenceManagerTests.js index 98039d7823..645ee8a59b 100644 --- a/services/document-updater/test/unit/js/PersistenceManager/PersistenceManagerTests.js +++ b/services/document-updater/test/unit/js/PersistenceManager/PersistenceManagerTests.js @@ -41,7 +41,8 @@ describe('PersistenceManager', function () { 'logger-sharelatex': (this.logger = { log: sinon.stub(), err: sinon.stub() - }) + }), + './Errors': Errors } }) this.project_id = 'project-id-123' @@ -171,7 +172,7 @@ describe('PersistenceManager', function () { it('should return a NotFoundError', function () { return this.callback - .calledWith(new Errors.NotFoundError('not found')) + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) .should.equal(true) }) @@ -198,7 +199,7 @@ describe('PersistenceManager', function () { it('should return an error', function () { return this.callback - .calledWith(new Error('web api error')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) @@ -231,7 +232,7 @@ describe('PersistenceManager', function () { return it('should return and error', function () { return this.callback - .calledWith(new Error('web API response had no doc lines')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -254,7 +255,7 @@ describe('PersistenceManager', function () { return it('should return and error', function () { return this.callback - .calledWith(new Error('web API response had no valid doc version')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -277,7 +278,7 @@ describe('PersistenceManager', function () { return it('should return and error', function () { return this.callback - .calledWith(new Error('web API response had no valid doc pathname')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -386,7 +387,7 @@ describe('PersistenceManager', function () { it('should return a NotFoundError', function () { return this.callback - .calledWith(new Errors.NotFoundError('not found')) + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) .should.equal(true) }) @@ -418,7 +419,7 @@ describe('PersistenceManager', function () { it('should return an error', function () { return this.callback - .calledWith(new Error('web api error')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) diff --git a/services/document-updater/test/unit/js/ProjectManager/flushAndDeleteProjectTests.js b/services/document-updater/test/unit/js/ProjectManager/flushAndDeleteProjectTests.js index 7afa407e7c..9589d42054 100644 --- a/services/document-updater/test/unit/js/ProjectManager/flushAndDeleteProjectTests.js +++ b/services/document-updater/test/unit/js/ProjectManager/flushAndDeleteProjectTests.js @@ -140,14 +140,16 @@ describe('ProjectManager - flushAndDeleteProject', function () { it('should record the error', function () { return this.logger.error .calledWith( - { err: this.error, project_id: this.project_id, doc_id: 'doc-id-1' }, + { err: this.error, projectId: this.project_id, docId: 'doc-id-1' }, 'error deleting doc' ) .should.equal(true) }) it('should call the callback with an error', function () { - return this.callback.calledWith(new Error()).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Error)) + .should.equal(true) }) return it('should time the execution', function () { diff --git a/services/document-updater/test/unit/js/ProjectManager/flushProjectTests.js b/services/document-updater/test/unit/js/ProjectManager/flushProjectTests.js index 110a827e64..c0bb668f49 100644 --- a/services/document-updater/test/unit/js/ProjectManager/flushProjectTests.js +++ b/services/document-updater/test/unit/js/ProjectManager/flushProjectTests.js @@ -129,14 +129,16 @@ describe('ProjectManager - flushProject', function () { it('should record the error', function () { return this.logger.error .calledWith( - { err: this.error, project_id: this.project_id, doc_id: 'doc-id-1' }, + { err: this.error, projectId: this.project_id, docId: 'doc-id-1' }, 'error flushing doc' ) .should.equal(true) }) it('should call the callback with an error', function () { - return this.callback.calledWith(new Error()).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Error)) + .should.equal(true) }) return it('should time the execution', function () { diff --git a/services/document-updater/test/unit/js/ProjectManager/getProjectDocsTests.js b/services/document-updater/test/unit/js/ProjectManager/getProjectDocsTests.js index 72ffe39ec1..db9f31e4ad 100644 --- a/services/document-updater/test/unit/js/ProjectManager/getProjectDocsTests.js +++ b/services/document-updater/test/unit/js/ProjectManager/getProjectDocsTests.js @@ -40,7 +40,8 @@ describe('ProjectManager - getProjectDocsAndFlushIfOld', function () { Timer.initClass() return Timer })()) - }) + }), + './Errors': Errors } }) this.project_id = 'project-id-123' @@ -146,9 +147,7 @@ describe('ProjectManager - getProjectDocsAndFlushIfOld', function () { it('should call the callback with an error', function () { return this.callback - .calledWith( - new Errors.ProjectStateChangedError('project state changed') - ) + .calledWith(sinon.match.instanceOf(Errors.ProjectStateChangedError)) .should.equal(true) }) @@ -187,14 +186,16 @@ describe('ProjectManager - getProjectDocsAndFlushIfOld', function () { it('should record the error', function () { return this.logger.error .calledWith( - { err: this.error, project_id: this.project_id, doc_id: 'doc-id-2' }, + { err: this.error, projectId: this.project_id, docId: 'doc-id-2' }, 'error getting project doc lines in getProjectDocsAndFlushIfOld' ) .should.equal(true) }) it('should call the callback with an error', function () { - return this.callback.calledWith(new Error('oops')).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Error)) + .should.equal(true) }) return it('should time the execution', function () { diff --git a/services/document-updater/test/unit/js/ProjectManager/updateProjectTests.js b/services/document-updater/test/unit/js/ProjectManager/updateProjectTests.js index 5b439ef839..aa3db813a0 100644 --- a/services/document-updater/test/unit/js/ProjectManager/updateProjectTests.js +++ b/services/document-updater/test/unit/js/ProjectManager/updateProjectTests.js @@ -1,46 +1,40 @@ -/* eslint-disable - no-return-assign, - no-unused-vars, -*/ -// TODO: This file was created by bulk-decaffeinate. -// Fix any style issues and re-enable lint. -/* - * decaffeinate suggestions: - * DS102: Remove unnecessary code created because of implicit returns - * DS206: Consider reworking classes to avoid initClass - * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md - */ const sinon = require('sinon') -const chai = require('chai') -const should = chai.should() const modulePath = '../../../../app/js/ProjectManager.js' const SandboxedModule = require('sandboxed-module') const _ = require('lodash') describe('ProjectManager', function () { beforeEach(function () { - let Timer + this.RedisManager = {} + this.ProjectHistoryRedisManager = { + queueRenameEntity: sinon.stub().yields(), + queueAddEntity: sinon.stub().yields() + } + this.DocumentManager = { + renameDocWithLock: sinon.stub().yields() + } + this.HistoryManager = { + flushProjectChangesAsync: sinon.stub(), + shouldFlushHistoryOps: sinon.stub().returns(false) + } + this.Metrics = { + Timer: class Timer {} + } + this.Metrics.Timer.prototype.done = sinon.stub() + + this.logger = { + log: sinon.stub(), + error: sinon.stub() + } + this.ProjectManager = SandboxedModule.require(modulePath, { requires: { - './RedisManager': (this.RedisManager = {}), - './ProjectHistoryRedisManager': (this.ProjectHistoryRedisManager = {}), - './DocumentManager': (this.DocumentManager = {}), - 'logger-sharelatex': (this.logger = { - log: sinon.stub(), - error: sinon.stub() - }), - './HistoryManager': (this.HistoryManager = {}), - './Metrics': (this.Metrics = { - Timer: (Timer = (function () { - Timer = class Timer { - static initClass() { - this.prototype.done = sinon.stub() - } - } - Timer.initClass() - return Timer - })()) - }) + './RedisManager': this.RedisManager, + './ProjectHistoryRedisManager': this.ProjectHistoryRedisManager, + './DocumentManager': this.DocumentManager, + 'logger-sharelatex': this.logger, + './HistoryManager': this.HistoryManager, + './Metrics': this.Metrics } }) @@ -48,45 +42,44 @@ describe('ProjectManager', function () { this.projectHistoryId = 'history-id-123' this.user_id = 'user-id-123' this.version = 1234567 - this.HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(false) - this.HistoryManager.flushProjectChangesAsync = sinon.stub() - return (this.callback = sinon.stub()) + this.callback = sinon.stub() }) - return describe('updateProjectWithLocks', function () { + describe('updateProjectWithLocks', function () { describe('rename operations', function () { beforeEach(function () { this.firstDocUpdate = { + type: 'rename-doc', id: 1, pathname: 'foo', newPathname: 'foo' } this.secondDocUpdate = { + type: 'rename-doc', id: 2, pathname: 'bar', newPathname: 'bar2' } - this.docUpdates = [this.firstDocUpdate, this.secondDocUpdate] this.firstFileUpdate = { + type: 'rename-file', id: 2, pathname: 'bar', newPathname: 'bar2' } - this.fileUpdates = [this.firstFileUpdate] - this.DocumentManager.renameDocWithLock = sinon.stub().yields() - return (this.ProjectHistoryRedisManager.queueRenameEntity = sinon - .stub() - .yields()) + this.updates = [ + this.firstDocUpdate, + this.secondDocUpdate, + this.firstFileUpdate + ] }) describe('successfully', function () { beforeEach(function () { - return this.ProjectManager.updateProjectWithLocks( + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) @@ -110,7 +103,7 @@ describe('ProjectManager', function () { this.projectHistoryId ) .should.equal(true) - return this.DocumentManager.renameDocWithLock + this.DocumentManager.renameDocWithLock .calledWith( this.project_id, this.secondDocUpdate.id, @@ -127,7 +120,7 @@ describe('ProjectManager', function () { this.firstFileUpdate, { version: `${this.version}.2` } ) - return this.ProjectHistoryRedisManager.queueRenameEntity + this.ProjectHistoryRedisManager.queueRenameEntity .calledWith( this.project_id, this.projectHistoryId, @@ -140,115 +133,112 @@ describe('ProjectManager', function () { }) it('should not flush the history', function () { - return this.HistoryManager.flushProjectChangesAsync + this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(false) }) - return it('should call the callback', function () { - return this.callback.called.should.equal(true) + it('should call the callback', function () { + this.callback.called.should.equal(true) }) }) describe('when renaming a doc fails', function () { beforeEach(function () { this.error = new Error('error') - this.DocumentManager.renameDocWithLock = sinon - .stub() - .yields(this.error) - return this.ProjectManager.updateProjectWithLocks( + this.DocumentManager.renameDocWithLock.yields(this.error) + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) }) - return it('should call the callback with the error', function () { - return this.callback.calledWith(this.error).should.equal(true) + it('should call the callback with the error', function () { + this.callback.calledWith(this.error).should.equal(true) }) }) describe('when renaming a file fails', function () { beforeEach(function () { this.error = new Error('error') - this.ProjectHistoryRedisManager.queueRenameEntity = sinon - .stub() - .yields(this.error) - return this.ProjectManager.updateProjectWithLocks( + this.ProjectHistoryRedisManager.queueRenameEntity.yields(this.error) + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) }) - return it('should call the callback with the error', function () { - return this.callback.calledWith(this.error).should.equal(true) + it('should call the callback with the error', function () { + this.callback.calledWith(this.error).should.equal(true) }) }) - return describe('with enough ops to flush', function () { + describe('with enough ops to flush', function () { beforeEach(function () { - this.HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(true) - return this.ProjectManager.updateProjectWithLocks( + this.HistoryManager.shouldFlushHistoryOps.returns(true) + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) }) - return it('should flush the history', function () { - return this.HistoryManager.flushProjectChangesAsync + it('should flush the history', function () { + this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(true) }) }) }) - return describe('add operations', function () { + describe('add operations', function () { beforeEach(function () { this.firstDocUpdate = { + type: 'add-doc', id: 1, docLines: 'a\nb' } this.secondDocUpdate = { + type: 'add-doc', id: 2, docLines: 'a\nb' } - this.docUpdates = [this.firstDocUpdate, this.secondDocUpdate] this.firstFileUpdate = { + type: 'add-file', id: 3, url: 'filestore.example.com/2' } this.secondFileUpdate = { + type: 'add-file', id: 4, url: 'filestore.example.com/3' } - this.fileUpdates = [this.firstFileUpdate, this.secondFileUpdate] - return (this.ProjectHistoryRedisManager.queueAddEntity = sinon - .stub() - .yields()) + this.updates = [ + this.firstDocUpdate, + this.secondDocUpdate, + this.firstFileUpdate, + this.secondFileUpdate + ] }) describe('successfully', function () { beforeEach(function () { - return this.ProjectManager.updateProjectWithLocks( + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) @@ -274,7 +264,7 @@ describe('ProjectManager', function () { firstDocUpdateWithVersion ) .should.equal(true) - return this.ProjectHistoryRedisManager.queueAddEntity + this.ProjectHistoryRedisManager.queueAddEntity .getCall(1) .calledWith( this.project_id, @@ -309,7 +299,7 @@ describe('ProjectManager', function () { firstFileUpdateWithVersion ) .should.equal(true) - return this.ProjectHistoryRedisManager.queueAddEntity + this.ProjectHistoryRedisManager.queueAddEntity .getCall(3) .calledWith( this.project_id, @@ -323,80 +313,91 @@ describe('ProjectManager', function () { }) it('should not flush the history', function () { - return this.HistoryManager.flushProjectChangesAsync + this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(false) }) - return it('should call the callback', function () { - return this.callback.called.should.equal(true) + it('should call the callback', function () { + this.callback.called.should.equal(true) }) }) describe('when adding a doc fails', function () { beforeEach(function () { this.error = new Error('error') - this.ProjectHistoryRedisManager.queueAddEntity = sinon - .stub() - .yields(this.error) - return this.ProjectManager.updateProjectWithLocks( + this.ProjectHistoryRedisManager.queueAddEntity.yields(this.error) + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) }) - return it('should call the callback with the error', function () { - return this.callback.calledWith(this.error).should.equal(true) + it('should call the callback with the error', function () { + this.callback.calledWith(this.error).should.equal(true) }) }) describe('when adding a file fails', function () { beforeEach(function () { this.error = new Error('error') - this.ProjectHistoryRedisManager.queueAddEntity = sinon - .stub() - .yields(this.error) - return this.ProjectManager.updateProjectWithLocks( + this.ProjectHistoryRedisManager.queueAddEntity.yields(this.error) + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) }) - return it('should call the callback with the error', function () { - return this.callback.calledWith(this.error).should.equal(true) + it('should call the callback with the error', function () { + this.callback.calledWith(this.error).should.equal(true) }) }) - return describe('with enough ops to flush', function () { + describe('with enough ops to flush', function () { beforeEach(function () { - this.HistoryManager.shouldFlushHistoryOps = sinon.stub().returns(true) - return this.ProjectManager.updateProjectWithLocks( + this.HistoryManager.shouldFlushHistoryOps.returns(true) + this.ProjectManager.updateProjectWithLocks( this.project_id, this.projectHistoryId, this.user_id, - this.docUpdates, - this.fileUpdates, + this.updates, this.version, this.callback ) }) - return it('should flush the history', function () { - return this.HistoryManager.flushProjectChangesAsync + it('should flush the history', function () { + this.HistoryManager.flushProjectChangesAsync .calledWith(this.project_id) .should.equal(true) }) }) }) + + describe('when given an unknown operation type', function () { + beforeEach(function () { + this.updates = [{ type: 'brew-coffee' }] + this.ProjectManager.updateProjectWithLocks( + this.project_id, + this.projectHistoryId, + this.user_id, + this.updates, + this.version, + this.callback + ) + }) + + it('should call back with an error', function () { + this.callback.calledWith(sinon.match.instanceOf(Error)).should.be.true + }) + }) }) }) diff --git a/services/document-updater/test/unit/js/RealTimeRedisManager/RealTimeRedisManagerTests.js b/services/document-updater/test/unit/js/RealTimeRedisManager/RealTimeRedisManagerTests.js index 9e2f2e270f..cda00ca9d8 100644 --- a/services/document-updater/test/unit/js/RealTimeRedisManager/RealTimeRedisManagerTests.js +++ b/services/document-updater/test/unit/js/RealTimeRedisManager/RealTimeRedisManagerTests.js @@ -118,7 +118,7 @@ describe('RealTimeRedisManager', function () { return it('should return an error to the callback', function () { return this.callback - .calledWith(new Error('JSON parse error')) + .calledWith(sinon.match.has('name', 'SyntaxError')) .should.equal(true) }) }) diff --git a/services/document-updater/test/unit/js/RedisManager/RedisManagerTests.js b/services/document-updater/test/unit/js/RedisManager/RedisManagerTests.js index e36df094f1..467c9a3c2f 100644 --- a/services/document-updater/test/unit/js/RedisManager/RedisManagerTests.js +++ b/services/document-updater/test/unit/js/RedisManager/RedisManagerTests.js @@ -398,7 +398,7 @@ describe('RedisManager', function () { return it('should return an error', function () { return this.callback - .calledWith(new Error('redis getDoc exceeded timeout')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -426,7 +426,7 @@ describe('RedisManager', function () { return it('should return an error', function () { return this.callback - .calledWith(new Errors.NotFoundError('not found')) + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) .should.equal(true) }) }) @@ -543,11 +543,7 @@ describe('RedisManager', function () { it('should return an error', function () { return this.callback - .calledWith( - new Errors.OpRangeNotAvailableError( - 'doc ops range is not loaded in redis' - ) - ) + .calledWith(sinon.match.instanceOf(Errors.OpRangeNotAvailableError)) .should.equal(true) }) @@ -588,7 +584,7 @@ describe('RedisManager', function () { return it('should return an error', function () { return this.callback - .calledWith(new Error('redis getPreviousDocOps exceeded timeout')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -854,9 +850,7 @@ describe('RedisManager', function () { return it('should call the callback with an error', function () { return this.callback - .calledWith( - new Error(`Version mismatch. '${this.doc_id}' is corrupted.`) - ) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -954,7 +948,7 @@ describe('RedisManager', function () { return it('should call the callback with an error', function () { return this.callback - .calledWith(new Error('null bytes found in doc lines')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -985,7 +979,7 @@ describe('RedisManager', function () { return it('should call the callback with the error', function () { return this.callback - .calledWith(new Error('ranges are too large')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -1157,7 +1151,7 @@ describe('RedisManager', function () { return it('should call the callback with an error', function () { return this.callback - .calledWith(new Error('null bytes found in doc lines')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) @@ -1185,7 +1179,7 @@ describe('RedisManager', function () { return it('should call the callback with the error', function () { return this.callback - .calledWith(new Error('ranges are too large')) + .calledWith(sinon.match.instanceOf(Error)) .should.equal(true) }) }) diff --git a/services/document-updater/test/unit/js/ShareJsDB/ShareJsDBTests.js b/services/document-updater/test/unit/js/ShareJsDB/ShareJsDBTests.js index 7f7d377c1d..ddf98775d8 100644 --- a/services/document-updater/test/unit/js/ShareJsDB/ShareJsDBTests.js +++ b/services/document-updater/test/unit/js/ShareJsDB/ShareJsDBTests.js @@ -26,7 +26,8 @@ describe('ShareJsDB', function () { this.callback = sinon.stub() this.ShareJsDB = SandboxedModule.require(modulePath, { requires: { - './RedisManager': (this.RedisManager = {}) + './RedisManager': (this.RedisManager = {}), + './Errors': Errors } }) @@ -68,7 +69,7 @@ describe('ShareJsDB', function () { return it('should return the callback with a NotFoundError', function () { return this.callback - .calledWith(new Errors.NotFoundError('not found')) + .calledWith(sinon.match.instanceOf(Errors.NotFoundError)) .should.equal(true) }) }) diff --git a/services/document-updater/test/unit/js/ShareJsUpdateManager/ShareJsUpdateManagerTests.js b/services/document-updater/test/unit/js/ShareJsUpdateManager/ShareJsUpdateManagerTests.js index 56afe4c584..ff8b74b8e6 100644 --- a/services/document-updater/test/unit/js/ShareJsUpdateManager/ShareJsUpdateManagerTests.js +++ b/services/document-updater/test/unit/js/ShareJsUpdateManager/ShareJsUpdateManagerTests.js @@ -194,7 +194,9 @@ describe('ShareJsUpdateManager', function () { }) return it('should call the callback with the error', function () { - return this.callback.calledWith(this.error).should.equal(true) + return this.callback + .calledWith(sinon.match.instanceOf(Error)) + .should.equal(true) }) }) })