let DocstoreClient const request = require('request').defaults({ jar: false }) const settings = require('@overleaf/settings') const Persistor = require('../../../../app/js/PersistorManager') async function streamToString(stream) { const chunks = [] return await new Promise((resolve, reject) => { stream.on('data', chunk => chunks.push(chunk)) stream.on('error', reject) stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8'))) }) } async function getStringFromPersistor(persistor, bucket, key) { const stream = await persistor.getObjectStream(bucket, key, {}) stream.resume() return await streamToString(stream) } module.exports = DocstoreClient = { createDoc(projectId, docId, lines, version, ranges, callback) { return DocstoreClient.updateDoc( projectId, docId, lines, version, ranges, callback ) }, getDoc(projectId, docId, qs, callback) { request.get( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}`, json: true, qs, }, callback ) }, peekDoc(projectId, docId, qs, callback) { request.get( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}/peek`, json: true, qs, }, callback ) }, isDocDeleted(projectId, docId, callback) { request.get( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}/deleted`, json: true, }, callback ) }, getAllDocs(projectId, callback) { request.get( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc`, json: true, }, (req, res, body) => { callback(req, res, body) } ) }, getAllDeletedDocs(projectId, callback) { request.get( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc-deleted`, json: true, }, (error, res, body) => { if (error) return callback(error) if (res.statusCode !== 200) { return callback(new Error('unexpected statusCode')) } callback(null, body) } ) }, getAllRanges(projectId, callback) { request.get( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/ranges`, json: true, }, callback ) }, updateDoc(projectId, docId, lines, version, ranges, callback) { return request.post( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}`, json: { lines, version, ranges, }, }, callback ) }, deleteDoc(projectId, docId, callback) { DocstoreClient.deleteDocWithDateAndName( projectId, docId, new Date(), 'main.tex', callback ) }, deleteDocWithDate(projectId, docId, date, callback) { DocstoreClient.deleteDocWithDateAndName( projectId, docId, date, 'main.tex', callback ) }, deleteDocWithName(projectId, docId, name, callback) { DocstoreClient.deleteDocWithDateAndName( projectId, docId, new Date(), name, callback ) }, deleteDocWithDateAndName(projectId, docId, deletedAt, name, callback) { request.patch( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}`, json: { name, deleted: true, deletedAt }, }, callback ) }, archiveAllDoc(projectId, callback) { request.post( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/archive`, }, callback ) }, archiveDoc(projectId, docId, callback) { request.post( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/doc/${docId}/archive`, }, callback ) }, destroyAllDoc(projectId, callback) { request.post( { url: `http://127.0.0.1:${settings.internal.docstore.port}/project/${projectId}/destroy`, }, callback ) }, getS3Doc(projectId, docId, callback) { getStringFromPersistor( Persistor, settings.docstore.bucket, `${projectId}/${docId}` ) .then(data => { callback(null, JSON.parse(data)) }) .catch(callback) }, }