/* eslint-disable handle-callback-err, max-len, 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 * DS103: Rewrite code to no longer use __guard__ * DS207: Consider shorter variations of null checks * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md */ let ReferencesHandler const OError = require('@overleaf/o-error') const logger = require('logger-sharelatex') const request = require('request') const settings = require('settings-sharelatex') const Features = require('../../infrastructure/Features') const ProjectGetter = require('../Project/ProjectGetter') const UserGetter = require('../User/UserGetter') const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler') const _ = require('underscore') const Async = require('async') const oneMinInMs = 60 * 1000 const fiveMinsInMs = oneMinInMs * 5 if (!Features.hasFeature('references')) { logger.log('references search not enabled') } module.exports = ReferencesHandler = { _buildDocUrl(projectId, docId) { return `${settings.apis.docstore.url}/project/${projectId}/doc/${docId}/raw` }, _buildFileUrl(projectId, fileId) { return `${settings.apis.filestore.url}/project/${projectId}/file/${fileId}` }, _findBibFileIds(project) { const ids = [] var _process = function(folder) { _.each(folder.fileRefs || [], function(file) { if ( __guard__(file != null ? file.name : undefined, x1 => x1.match(/^.*\.bib$/) ) ) { return ids.push(file._id) } }) return _.each(folder.folders || [], folder => _process(folder)) } _.each(project.rootFolder || [], rootFolder => _process(rootFolder)) return ids }, _findBibDocIds(project) { const ids = [] var _process = function(folder) { _.each(folder.docs || [], function(doc) { if ( __guard__(doc != null ? doc.name : undefined, x1 => x1.match(/^.*\.bib$/) ) ) { return ids.push(doc._id) } }) return _.each(folder.folders || [], folder => _process(folder)) } _.each(project.rootFolder || [], rootFolder => _process(rootFolder)) return ids }, _isFullIndex(project, callback) { if (callback == null) { callback = function(err, result) {} } return UserGetter.getUser(project.owner_ref, { features: true }, function( err, owner ) { if (err != null) { return callback(err) } const features = owner != null ? owner.features : undefined return callback( null, (features != null ? features.references : undefined) === true || (features != null ? features.referencesSearch : undefined) === true ) }) }, indexAll(projectId, callback) { if (callback == null) { callback = function(err, data) {} } return ProjectGetter.getProject( projectId, { rootFolder: true, owner_ref: 1 }, function(err, project) { if (err) { OError.tag(err, 'error finding project', { projectId }) return callback(err) } logger.log({ projectId }, 'indexing all bib files in project') const docIds = ReferencesHandler._findBibDocIds(project) const fileIds = ReferencesHandler._findBibFileIds(project) return ReferencesHandler._doIndexOperation( projectId, project, docIds, fileIds, callback ) } ) }, index(projectId, docIds, callback) { if (callback == null) { callback = function(err, data) {} } return ProjectGetter.getProject( projectId, { rootFolder: true, owner_ref: 1 }, function(err, project) { if (err) { OError.tag(err, 'error finding project', { projectId }) return callback(err) } return ReferencesHandler._doIndexOperation( projectId, project, docIds, [], callback ) } ) }, _doIndexOperation(projectId, project, docIds, fileIds, callback) { if (!Features.hasFeature('references')) { return callback() } return ReferencesHandler._isFullIndex(project, function(err, isFullIndex) { if (err) { OError.tag(err, 'error checking whether to do full index', { projectId }) return callback(err) } logger.log( { projectId, docIds }, 'flushing docs to mongo before calling references service' ) return Async.series( docIds.map(docId => cb => DocumentUpdaterHandler.flushDocToMongo(projectId, docId, cb) ), function(err) { // continue if (err) { OError.tag(err, 'error flushing docs to mongo', { projectId, docIds }) return callback(err) } const bibDocUrls = docIds.map(docId => ReferencesHandler._buildDocUrl(projectId, docId) ) const bibFileUrls = fileIds.map(fileId => ReferencesHandler._buildFileUrl(projectId, fileId) ) const allUrls = bibDocUrls.concat(bibFileUrls) return request.post( { url: `${settings.apis.references.url}/project/${projectId}/index`, json: { docUrls: allUrls, fullIndex: isFullIndex } }, function(err, res, data) { if (err) { OError.tag(err, 'error communicating with references api', { projectId }) return callback(err) } if (res.statusCode >= 200 && res.statusCode < 300) { logger.log({ projectId }, 'got keys from references api') return callback(null, data) } else { err = new Error( `references api responded with non-success code: ${ res.statusCode }` ) return callback(err) } } ) } ) }) } } function __guard__(value, transform) { return typeof value !== 'undefined' && value !== null ? transform(value) : undefined }