Merge pull request #18289 from overleaf/ac-ar-eslint-return-await

Add ESLint rule @typescript-eslint/return-await to backend services

GitOrigin-RevId: 75e3e32597827fcc852e69d479515fc72e8f45e4
This commit is contained in:
Andrew Rumble 2024-05-22 10:37:08 +01:00 committed by Copybot
parent 029cd4abe7
commit 71187a51ba
43 changed files with 1180 additions and 411 deletions

View file

@ -80,7 +80,13 @@ class AccessTokenSchemeWithGenericKeyFn extends AbstractAccessTokenScheme {
class AccessTokenSchemeV3 extends AccessTokenSchemeWithGenericKeyFn {
async keyFn(salt) {
const optionalInfo = ''
return cryptoHkdf('sha512', this.cipherPassword, salt, optionalInfo, 32)
return await cryptoHkdf(
'sha512',
this.cipherPassword,
salt,
optionalInfo,
32
)
}
}

View file

@ -10,7 +10,7 @@ const DRY_RUN = !process.argv.includes('--dry-run=false')
* @return {Promise<string>}
*/
async function reEncryptTokens(accessTokenEncryptor, encryptedJson) {
return new Promise((resolve, reject) => {
return await new Promise((resolve, reject) => {
accessTokenEncryptor.decryptToJson(encryptedJson, (err, json) => {
if (err) return reject(err)
accessTokenEncryptor.encryptJson(json, (err, reEncryptedJson) => {

View file

@ -239,6 +239,11 @@ async function discardResponseBody(response) {
}
}
/**
* @typedef {import('node-fetch').Response} Response
*
* @param {Response} response
*/
async function maybeGetResponseBody(response) {
try {
return await response.text()

View file

@ -16,6 +16,7 @@
"author": "Overleaf (https://www.overleaf.com)",
"license": "AGPL-3.0-only",
"devDependencies": {
"@types/node-fetch": "^2.6.11",
"body-parser": "^1.20.2",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",

View file

@ -42,7 +42,7 @@ module.exports = class GcsPersistor extends AbstractPersistor {
}
async sendFile(bucketName, key, fsPath) {
return this.sendStream(bucketName, key, fs.createReadStream(fsPath))
return await this.sendStream(bucketName, key, fs.createReadStream(fsPath))
}
async sendStream(bucketName, key, readStream, opts = {}) {

View file

@ -17,55 +17,65 @@ const { NotFoundError, WriteError } = require('./Errors')
// }
module.exports = class MigrationPersistor extends AbstractPersistor {
/**
* @param {AbstractPersistor} primaryPersistor
* @param {AbstractPersistor} fallbackPersistor
* @param settings
*/
constructor(primaryPersistor, fallbackPersistor, settings) {
super()
/**
* @type {AbstractPersistor}
*/
this.primaryPersistor = primaryPersistor
/**
* @type {AbstractPersistor}
*/
this.fallbackPersistor = fallbackPersistor
this.settings = settings
}
async sendFile(...args) {
return this.primaryPersistor.sendFile(...args)
return await this.primaryPersistor.sendFile(...args)
}
async sendStream(...args) {
return this.primaryPersistor.sendStream(...args)
return await this.primaryPersistor.sendStream(...args)
}
async getRedirectUrl(...args) {
return this.primaryPersistor.getRedirectUrl(...args)
return await this.primaryPersistor.getRedirectUrl(...args)
}
async getObjectMd5Hash(...args) {
return this._runWithFallback('getObjectMd5Hash', ...args)
return await this._runWithFallback('getObjectMd5Hash', ...args)
}
async checkIfObjectExists(...args) {
return this._runWithFallback('checkIfObjectExists', ...args)
return await this._runWithFallback('checkIfObjectExists', ...args)
}
async getObjectSize(...args) {
return this._runWithFallback('getObjectSize', ...args)
return await this._runWithFallback('getObjectSize', ...args)
}
async directorySize(...args) {
return this._runWithFallback('directorySize', ...args)
return await this._runWithFallback('directorySize', ...args)
}
async deleteObject(...args) {
return this._runOnBoth('deleteObject', ...args)
return await this._runOnBoth('deleteObject', ...args)
}
async deleteDirectory(...args) {
return this._runOnBoth('deleteDirectory', ...args)
return await this._runOnBoth('deleteDirectory', ...args)
}
async getObjectStream(bucket, key, opts = {}) {
const shouldCopy = this.settings.copyOnMiss && !opts.start && !opts.end
try {
// 'return await' so we catch NotFoundError before returning
return await this.primaryPersistor.getObjectStream(bucket, key, opts)
} catch (err) {
if (err instanceof NotFoundError) {
@ -140,7 +150,7 @@ module.exports = class MigrationPersistor extends AbstractPersistor {
})
}
// copy from sourceKey -> destKey
return this._copyStreamFromFallbackAndVerify(
return await this._copyStreamFromFallbackAndVerify(
copyStream,
fallbackBucket,
bucket,
@ -217,9 +227,14 @@ module.exports = class MigrationPersistor extends AbstractPersistor {
])
}
/**
* @param {keyof AbstractPersistor} methodName
* @param bucket
* @param key
* @param moreArgs
*/
async _runWithFallback(methodName, bucket, key, ...moreArgs) {
try {
// 'return await' so we catch NotFoundError before returning
return await this.primaryPersistor[methodName](bucket, key, ...moreArgs)
} catch (err) {
if (err instanceof NotFoundError) {
@ -241,7 +256,7 @@ module.exports = class MigrationPersistor extends AbstractPersistor {
Logger.warn({ err }, 'failed to copy file from fallback')
})
}
return this.fallbackPersistor[methodName](
return await this.fallbackPersistor[methodName](
fallbackBucket,
key,
...moreArgs

View file

@ -24,7 +24,7 @@ module.exports = class S3Persistor extends AbstractPersistor {
}
async sendFile(bucketName, key, fsPath) {
return this.sendStream(bucketName, key, fs.createReadStream(fsPath))
return await this.sendStream(bucketName, key, fs.createReadStream(fsPath))
}
async sendStream(bucketName, key, readStream, opts = {}) {
@ -231,7 +231,7 @@ module.exports = class S3Persistor extends AbstractPersistor {
if (this.settings.Metrics) {
this.settings.Metrics.inc('s3.md5Download')
}
return PersistorHelper.calculateStreamMd5(
return await PersistorHelper.calculateStreamMd5(
await this.getObjectStream(bucketName, key)
)
} catch (err) {

View file

@ -225,7 +225,7 @@ describe('MigrationPersistorTests', function () {
newPersistor(false),
Settings
)
return expect(
await expect(
migrationPersistor.getObjectStream(bucket, key)
).to.eventually.be.rejected.and.be.an.instanceOf(Errors.NotFoundError)
})
@ -322,7 +322,7 @@ describe('MigrationPersistorTests', function () {
describe('when the primary persistor throws an error', function () {
it('returns the error', async function () {
primaryPersistor.sendStream.rejects(notFoundError)
return expect(
await expect(
migrationPersistor.sendStream(bucket, key, fileStream)
).to.eventually.be.rejected.and.be.an.instanceOf(Errors.NotFoundError)
})

View file

@ -155,7 +155,7 @@ class LazyStringFileData extends FileData {
}
const eager = await this.toEager(blobStore)
this.operations.length = 0
return eager.store(blobStore)
return await eager.store(blobStore)
}
}

View file

@ -25,6 +25,7 @@ class History {
assert.maybe.array.of.instance(changes, Change, 'bad changes')
this.snapshot = snapshot
/** @type {Array<Change>} */
this.changes = changes || []
}
@ -113,6 +114,9 @@ class History {
async store(blobStore, concurrency) {
assert.maybe.number(concurrency, 'bad concurrency')
/**
* @param {Change} change
*/
async function storeChange(change) {
return await change.store(blobStore, concurrency)
}

1373
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,7 @@
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"@typescript-eslint/eslint-plugin": "^6.7.4",
"eslint": "^8.15.0",
"eslint-config-prettier": "^8.5.0",
"eslint-config-standard": "^17.0.0",

View file

@ -7,7 +7,7 @@ import { ObjectId } from '../../mongodb.js'
const DEFAULT_MESSAGE_LIMIT = 50
const MAX_MESSAGE_LENGTH = 10 * 1024 // 10kb, about 1,500 words
async function readContext(context, req) {
function readContext(context, req) {
req.body = context.requestBody
req.params = context.params.path
req.query = context.params.query
@ -23,6 +23,11 @@ async function readContext(context, req) {
}
}
/**
* @param context
* @param {(req: unknown, res: unknown) => Promise<unknown>} ControllerMethod
* @returns {Promise<*>}
*/
export async function callMessageHttpController(context, ControllerMethod) {
const req = {}
readContext(context, req)

View file

@ -19,11 +19,15 @@ export async function getMessages(roomId, limit, before) {
query.timestamp = { $lt: before }
}
query = _ensureIdsAreObjectIds(query)
return db.messages.find(query).sort({ timestamp: -1 }).limit(limit).toArray()
return await db.messages
.find(query)
.sort({ timestamp: -1 })
.limit(limit)
.toArray()
}
export async function findAllMessagesInRooms(roomIds) {
return db.messages
return await db.messages
.find({
room_id: { $in: roomIds },
})

View file

@ -37,7 +37,7 @@ export async function findOrCreateThread(projectId, threadId) {
}
export async function findAllThreadRooms(projectId) {
return db.rooms
return await db.rooms
.find(
{
project_id: new ObjectId(projectId.toString()),
@ -52,7 +52,7 @@ export async function findAllThreadRooms(projectId) {
}
export async function findAllThreadRoomsAndGlobalThread(projectId) {
return db.rooms
return await db.rooms
.find(
{
project_id: new ObjectId(projectId.toString()),

View file

@ -5,7 +5,7 @@ const request = Request.defaults({
})
async function asyncRequest(options) {
return new Promise((resolve, reject) => {
return await new Promise((resolve, reject) => {
request(options, (err, response, body) => {
if (err) {
reject(err)
@ -17,7 +17,7 @@ async function asyncRequest(options) {
}
export async function sendGlobalMessage(projectId, userId, content) {
return asyncRequest({
return await asyncRequest({
method: 'post',
url: `/project/${projectId}/messages`,
json: {
@ -28,7 +28,7 @@ export async function sendGlobalMessage(projectId, userId, content) {
}
export async function getGlobalMessages(projectId) {
return asyncRequest({
return await asyncRequest({
method: 'get',
url: `/project/${projectId}/messages`,
json: true,
@ -36,7 +36,7 @@ export async function getGlobalMessages(projectId) {
}
export async function sendMessage(projectId, threadId, userId, content) {
return asyncRequest({
return await asyncRequest({
method: 'post',
url: `/project/${projectId}/thread/${threadId}/messages`,
json: {
@ -47,7 +47,7 @@ export async function sendMessage(projectId, threadId, userId, content) {
}
export async function getThreads(projectId) {
return asyncRequest({
return await asyncRequest({
method: 'get',
url: `/project/${projectId}/threads`,
json: true,
@ -55,7 +55,7 @@ export async function getThreads(projectId) {
}
export async function resolveThread(projectId, threadId, userId) {
return asyncRequest({
return await asyncRequest({
method: 'post',
url: `/project/${projectId}/thread/${threadId}/resolve`,
json: {
@ -65,7 +65,7 @@ export async function resolveThread(projectId, threadId, userId) {
}
export async function getResolvedThreadIds(projectId) {
return asyncRequest({
return await asyncRequest({
method: 'get',
url: `/project/${projectId}/resolved-thread-ids`,
json: true,
@ -73,7 +73,7 @@ export async function getResolvedThreadIds(projectId) {
}
export async function editMessage(projectId, threadId, messageId, content) {
return asyncRequest({
return await asyncRequest({
method: 'post',
url: `/project/${projectId}/thread/${threadId}/messages/${messageId}/edit`,
json: {
@ -89,7 +89,7 @@ export async function editMessageWithUser(
userId,
content
) {
return asyncRequest({
return await asyncRequest({
method: 'post',
url: `/project/${projectId}/thread/${threadId}/messages/${messageId}/edit`,
json: {
@ -100,7 +100,7 @@ export async function editMessageWithUser(
}
export async function checkStatus() {
return asyncRequest({
return await asyncRequest({
method: 'get',
url: `/status`,
json: true,
@ -118,28 +118,28 @@ export async function getMetric(matcher) {
}
export async function reopenThread(projectId, threadId) {
return asyncRequest({
return await asyncRequest({
method: 'post',
url: `/project/${projectId}/thread/${threadId}/reopen`,
})
}
export async function deleteThread(projectId, threadId) {
return asyncRequest({
return await asyncRequest({
method: 'delete',
url: `/project/${projectId}/thread/${threadId}`,
})
}
export async function deleteMessage(projectId, threadId, messageId) {
return asyncRequest({
return await asyncRequest({
method: 'delete',
url: `/project/${projectId}/thread/${threadId}/messages/${messageId}`,
})
}
export async function destroyProject(projectId) {
return asyncRequest({
return await asyncRequest({
method: 'delete',
url: `/project/${projectId}`,
})

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -18,6 +18,9 @@ const {
const workerpool = require('workerpool')
const Metrics = require('@overleaf/metrics')
/**
* @type {import('workerpool').WorkerPool}
*/
let WORKER_POOL
// NOTE: Check for main thread to avoid recursive start of pool.
if (Settings.pdfCachingEnableWorkerPool && workerpool.isMainThread) {

View file

@ -74,7 +74,7 @@ async function runBulkCleanup() {
}
async function cleanupDirectory(dir, options) {
return queueDirOperation(dir, async () => {
return await queueDirOperation(dir, async () => {
try {
await OutputCacheManager.promises.expireOutputFiles(dir, options)
} catch (err) {

View file

@ -37,6 +37,7 @@
"workerpool": "^6.1.5"
},
"devDependencies": {
"@types/workerpool": "^6.1.0",
"chai": "^4.3.6",
"chai-as-promised": "^7.1.1",
"mocha": "^10.2.0",

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -203,7 +203,7 @@ async function _streamToBuffer(projectId, docId, stream) {
)
logged = true
}
return new Promise((resolve, reject) => {
return await new Promise((resolve, reject) => {
stream.on('data', chunk => {
size += chunk.byteLength
logIfTooLarge(false)

View file

@ -8,7 +8,19 @@ const Settings = require('@overleaf/settings')
const { callbackifyAll } = require('@overleaf/promise-utils')
const { setTimeout } = require('timers/promises')
/**
* @typedef {import('mongodb').Document} Document
* @typedef {import('mongodb').WithId} WithId
*/
const DocManager = {
/**
* @param {string} projectId
* @param {string} docId
* @param {{inS3: boolean}} filter
* @returns {Promise<WithId<Document>>}
* @private
*/
async _getDoc(projectId, docId, filter) {
if (filter == null) {
filter = {}

View file

@ -5,7 +5,7 @@ const Persistor = require('../../../../app/js/PersistorManager')
async function streamToString(stream) {
const chunks = []
return new Promise((resolve, reject) => {
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')))
@ -15,7 +15,7 @@ async function streamToString(stream) {
async function getStringFromPersistor(persistor, bucket, key) {
const stream = await persistor.getObjectStream(bucket, key, {})
stream.resume()
return streamToString(stream)
return await streamToString(stream)
}
module.exports = DocstoreClient = {

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -2,7 +2,7 @@ const ProjectFlusher = require('../app/js/ProjectFlusher')
async function main() {
console.log('Flushing all projects')
return new Promise((resolve, reject) => {
return await new Promise((resolve, reject) => {
const options = {
limit: 100000,
concurrency: 5,

View file

@ -2,7 +2,10 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"expire_docops.js",
"app/js/**/*",
"benchmarks/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -22,7 +22,7 @@ module.exports = {
async function convert(sourcePath, requestedFormat) {
const width = '600x'
return _convert(sourcePath, requestedFormat, [
return await _convert(sourcePath, requestedFormat, [
'convert',
'-define',
`pdf:fit-page=${width}`,
@ -35,7 +35,7 @@ async function convert(sourcePath, requestedFormat) {
async function thumbnail(sourcePath) {
const width = '260x'
return convert(sourcePath, 'png', [
return await convert(sourcePath, 'png', [
'convert',
'-flatten',
'-background',
@ -52,7 +52,7 @@ async function thumbnail(sourcePath) {
async function preview(sourcePath) {
const width = '548x'
return convert(sourcePath, 'png', [
return await convert(sourcePath, 'png', [
'convert',
'-flatten',
'-background',

View file

@ -72,9 +72,9 @@ async function deleteProject(bucket, key) {
async function getFile(bucket, key, opts) {
opts = opts || {}
if (!opts.format && !opts.style) {
return PersistorManager.getObjectStream(bucket, key, opts)
return await PersistorManager.getObjectStream(bucket, key, opts)
} else {
return _getConvertedFile(bucket, key, opts)
return await _getConvertedFile(bucket, key, opts)
}
}
@ -114,7 +114,7 @@ async function getRedirectUrl(bucket, key, opts) {
}
async function getFileSize(bucket, key) {
return PersistorManager.getObjectSize(bucket, key)
return await PersistorManager.getObjectSize(bucket, key)
}
async function getDirectorySize(bucket, projectId) {
@ -128,9 +128,9 @@ async function _getConvertedFile(bucket, key, opts) {
convertedKey
)
if (exists) {
return PersistorManager.getObjectStream(bucket, convertedKey, opts)
return await PersistorManager.getObjectStream(bucket, convertedKey, opts)
} else {
return _getConvertedFileAndCache(bucket, key, convertedKey, opts)
return await _getConvertedFileAndCache(bucket, key, convertedKey, opts)
}
}
@ -212,5 +212,5 @@ async function _convertFile(bucket, originalKey, opts) {
async function _writeFileToDisk(bucket, key, opts) {
const fileStream = await PersistorManager.getObjectStream(bucket, key, opts)
return LocalFileWriter.promises.writeStream(fileStream, key)
return await LocalFileWriter.promises.writeStream(fileStream, key)
}

View file

@ -23,7 +23,7 @@ class FilestoreApp {
}
if (this.initing) {
return this.waitForInit()
return await this.waitForInit()
}
this.initing = true

View file

@ -332,7 +332,7 @@ describe('Filestore', function () {
]
before(async function () {
return Promise.all([
return await Promise.all([
fsWriteFile(localFileReadPaths[0], constantFileContents[0]),
fsWriteFile(localFileReadPaths[1], constantFileContents[1]),
fsWriteFile(localFileReadPaths[2], constantFileContents[2]),

View file

@ -38,7 +38,7 @@ async function uploadStringToPersistor(persistor, bucket, key, content) {
async function getStringFromPersistor(persistor, bucket, key) {
const stream = await persistor.getObjectStream(bucket, key, {})
return streamToString(stream)
return await streamToString(stream)
}
async function expectPersistorToHaveFile(persistor, bucket, key, content) {

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -216,7 +216,7 @@ class BlobStore {
async putObject(obj) {
assert.object(obj, 'bad object')
const string = JSON.stringify(obj)
return this.putString(string)
return await this.putString(string)
}
/**

View file

@ -82,7 +82,7 @@ async function run(options) {
const results = await BPromise.map(
projectIds,
async projectId =>
processProject(
await processProject(
projectId,
chunkIdsByProject.get(projectId),
globalBlobs

View file

@ -99,7 +99,7 @@ async function expectChunksExist(minChunkId, maxChunkId, expected) {
keys.push(`100/000/000/${i.toString().padStart(9, '0')}`)
keys.push(`fed/cba/fedcbafedcbafedcba/${i.toString().padStart(24, '0')}`)
}
return Promise.all(
return await Promise.all(
keys.map(async key => {
const exists = await persistor.checkIfObjectExists(
CHUNK_STORE_BUCKET,

View file

@ -2,7 +2,12 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"api/**/*",
"app/js/**/*",
"benchmarks/**/*",
"config/**/*",
"migrations/**/*",
"storage/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -293,7 +293,7 @@ async function runWithLockPromises(key, runner) {
})
}
return new Promise((resolve, reject) => {
return await new Promise((resolve, reject) => {
runWithLock(key, runnerCb, (err, result) => {
if (err) {
reject(err)

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]

View file

@ -2,7 +2,8 @@
"extends": "../../tsconfig.backend.json",
"include": [
"app.js",
"app/src/**/*",
"app/js/**/*",
"config/**/*",
"scripts/**/*",
"test/**/*"
]