diff --git a/libraries/object-persistor/test/unit/FSPersistorTests.js b/libraries/object-persistor/test/unit/FSPersistorTests.js
index 220c7f95e4..804de81849 100644
--- a/libraries/object-persistor/test/unit/FSPersistorTests.js
+++ b/libraries/object-persistor/test/unit/FSPersistorTests.js
@@ -114,9 +114,8 @@ describe('FSPersistorTests', function () {
})
it('should not write the target file', async function () {
- await expect(
- fsPromises.access(scenario.fsPath(files.wombat))
- ).to.be.rejected
+ await expect(fsPromises.access(scenario.fsPath(files.wombat))).to
+ .be.rejected
})
it('should delete the temporary file', async function () {
@@ -135,9 +134,8 @@ describe('FSPersistorTests', function () {
const contents = await fsPromises.readFile(
scenario.fsPath(files.wombat)
)
- expect(
- contents.equals(localFiles['/uploads/info.txt'])
- ).to.be.true
+ expect(contents.equals(localFiles['/uploads/info.txt'])).to.be
+ .true
})
})
@@ -151,9 +149,8 @@ describe('FSPersistorTests', function () {
})
it('should not write the target file', async function () {
- await expect(
- fsPromises.access(scenario.fsPath(files.wombat))
- ).to.be.rejected
+ await expect(fsPromises.access(scenario.fsPath(files.wombat))).to
+ .be.rejected
})
it('should delete the temporary file', async function () {
@@ -203,9 +200,8 @@ describe('FSPersistorTests', function () {
const contents = await fsPromises.readFile(
scenario.fsPath(files.wombat)
)
- expect(
- contents.equals(localFiles['/uploads/info.txt'])
- ).to.be.true
+ expect(contents.equals(localFiles['/uploads/info.txt'])).to.be
+ .true
})
it('should delete the temporary file', async function () {
@@ -224,9 +220,8 @@ describe('FSPersistorTests', function () {
const contents = await fsPromises.readFile(
scenario.fsPath(files.wombat)
)
- expect(
- contents.equals(localFiles['/uploads/other.txt'])
- ).to.be.true
+ expect(contents.equals(localFiles['/uploads/other.txt'])).to.be
+ .true
})
})
@@ -243,9 +238,8 @@ describe('FSPersistorTests', function () {
const contents = await fsPromises.readFile(
scenario.fsPath(files.wombat)
)
- expect(
- contents.equals(localFiles['/uploads/info.txt'])
- ).to.be.true
+ expect(contents.equals(localFiles['/uploads/info.txt'])).to.be
+ .true
})
it('should delete the temporary file', async function () {
@@ -280,9 +274,8 @@ describe('FSPersistorTests', function () {
)
const contents = await streamToBuffer(stream)
// end is inclusive in ranges, but exclusive in slice()
- expect(
- contents.equals(localFiles['/uploads/info.txt'].slice(5, 17))
- ).to.be.true
+ expect(contents.equals(localFiles['/uploads/info.txt'].slice(5, 17)))
+ .to.be.true
})
it('should give a NotFoundError if the file does not exist', async function () {
@@ -332,9 +325,8 @@ describe('FSPersistorTests', function () {
it('should delete the file', async function () {
await persistor.deleteObject(location, files.wombat)
- await expect(
- fsPromises.access(scenario.fsPath(files.wombat))
- ).to.be.rejected
+ await expect(fsPromises.access(scenario.fsPath(files.wombat))).to.be
+ .rejected
})
it("should ignore files that don't exist", async function () {
diff --git a/libraries/overleaf-editor-core/lib/operation/text_operation.js b/libraries/overleaf-editor-core/lib/operation/text_operation.js
index 7efe7fb1d8..8b0b41a971 100644
--- a/libraries/overleaf-editor-core/lib/operation/text_operation.js
+++ b/libraries/overleaf-editor-core/lib/operation/text_operation.js
@@ -792,8 +792,8 @@ function getSimpleOp(operation) {
return ops[0] instanceof RetainOp
? ops[1]
: ops[1] instanceof RetainOp
- ? ops[0]
- : null
+ ? ops[0]
+ : null
case 3:
if (ops[0] instanceof RetainOp && ops[2] instanceof RetainOp) {
return ops[1]
diff --git a/package-lock.json b/package-lock.json
index e943887650..079633451e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -49,7 +49,7 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
- "prettier": "2.5.1",
+ "prettier": "3.2.5",
"resolve-url-loader": "^5.0.0",
"sass": "^1.69.5",
"sass-loader": "^13.3.2",
@@ -35248,15 +35248,18 @@
}
},
"node_modules/prettier": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
- "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
"dev": true,
"bin": {
- "prettier": "bin-prettier.js"
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-linter-helpers": {
@@ -44299,7 +44302,6 @@
"postcss-loader": "^7.3.0",
"postcss-preset-env": "^8.3.2",
"postcss-reporter": "^7.0.5",
- "prettier": "^2.5.1",
"react-test-renderer": "^16.7.0",
"react-transform-hmr": "^1.0.4",
"redux-mock-store": "1.5.0",
@@ -72046,7 +72048,6 @@
"postcss-loader": "^7.3.0",
"postcss-preset-env": "^8.3.2",
"postcss-reporter": "^7.0.5",
- "prettier": "^2.5.1",
"prop-types": "^15.8.1",
"react": "^16.8.6",
"react-bootstrap": "^0.31.5",
@@ -77090,9 +77091,9 @@
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
},
"prettier": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
- "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
+ "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==",
"dev": true
},
"prettier-linter-helpers": {
diff --git a/package.json b/package.json
index f868562347..f092472caf 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0",
- "prettier": "2.5.1",
+ "prettier": "3.2.5",
"resolve-url-loader": "^5.0.0",
"sass": "^1.69.5",
"sass-loader": "^13.3.2",
diff --git a/server-ce/config/settings.js b/server-ce/config/settings.js
index b70b9226fa..12e6296353 100644
--- a/server-ce/config/settings.js
+++ b/server-ce/config/settings.js
@@ -382,9 +382,7 @@ if (process.env.OVERLEAF_EMAIL_FROM_ADDRESS != null) {
// i18n
if (process.env.OVERLEAF_LANG_DOMAIN_MAPPING != null) {
- settings.i18n.subdomainLang = parse(
- process.env.OVERLEAF_LANG_DOMAIN_MAPPING
- )
+ settings.i18n.subdomainLang = parse(process.env.OVERLEAF_LANG_DOMAIN_MAPPING)
}
// Password Settings
diff --git a/server-ce/services.js b/server-ce/services.js
index a58892d5ed..e91e252ea9 100644
--- a/server-ce/services.js
+++ b/server-ce/services.js
@@ -1,39 +1,39 @@
module.exports = [
{
- name: 'web'
+ name: 'web',
},
{
- name: 'real-time'
+ name: 'real-time',
},
{
- name: 'document-updater'
+ name: 'document-updater',
},
{
- name: 'clsi'
+ name: 'clsi',
},
{
- name: 'filestore'
+ name: 'filestore',
},
{
- name: 'docstore'
+ name: 'docstore',
},
{
- name: 'chat'
+ name: 'chat',
},
{
- name: 'spelling'
+ name: 'spelling',
},
{
- name: 'contacts'
+ name: 'contacts',
},
{
- name: 'notifications'
+ name: 'notifications',
},
{
- name: 'project-history'
+ name: 'project-history',
},
{
- name: 'history-v1'
+ name: 'history-v1',
},
]
diff --git a/services/chat/test/acceptance/js/DestroyingAProjectTests.js b/services/chat/test/acceptance/js/DestroyingAProjectTests.js
index 0a92181994..95c6c35033 100644
--- a/services/chat/test/acceptance/js/DestroyingAProjectTests.js
+++ b/services/chat/test/acceptance/js/DestroyingAProjectTests.js
@@ -47,9 +47,8 @@ describe('Destroying a project', async function () {
const globalThreadMessage = await getMessage(this.globalThreadMessageId)
expect(globalThreadMessage).to.exist
- const { response: responseDestroy } = await ChatClient.destroyProject(
- projectId
- )
+ const { response: responseDestroy } =
+ await ChatClient.destroyProject(projectId)
expect(responseDestroy.statusCode).to.equal(204)
})
diff --git a/services/chat/test/acceptance/js/EditingAMessageTests.js b/services/chat/test/acceptance/js/EditingAMessageTests.js
index df17a32432..39f7edb28c 100644
--- a/services/chat/test/acceptance/js/EditingAMessageTests.js
+++ b/services/chat/test/acceptance/js/EditingAMessageTests.js
@@ -43,9 +43,8 @@ describe('Editing a message', async function () {
})
it('should then list the updated message in the threads', async function () {
- const { response, body: threads } = await ChatClient.getThreads(
- projectId
- )
+ const { response, body: threads } =
+ await ChatClient.getThreads(projectId)
expect(response.statusCode).to.equal(200)
expect(threads[threadId].messages.length).to.equal(1)
expect(threads[threadId].messages[0].content).to.equal(newContent)
@@ -65,9 +64,8 @@ describe('Editing a message', async function () {
})
it('should then list the updated message in the threads', async function () {
- const { response, body: threads } = await ChatClient.getThreads(
- projectId
- )
+ const { response, body: threads } =
+ await ChatClient.getThreads(projectId)
expect(response.statusCode).to.equal(200)
expect(threads[threadId].messages.length).to.equal(1)
expect(threads[threadId].messages[0].content).to.equal(newContent)
@@ -87,9 +85,8 @@ describe('Editing a message', async function () {
})
it('should then list the old message in the threads', async function () {
- const { response, body: threads } = await ChatClient.getThreads(
- projectId
- )
+ const { response, body: threads } =
+ await ChatClient.getThreads(projectId)
expect(response.statusCode).to.equal(200)
expect(threads[threadId].messages.length).to.equal(1)
expect(threads[threadId].messages[0].content).to.equal(content)
diff --git a/services/chat/test/acceptance/js/GettingMessagesTests.js b/services/chat/test/acceptance/js/GettingMessagesTests.js
index d53428901f..af6a0624a9 100644
--- a/services/chat/test/acceptance/js/GettingMessagesTests.js
+++ b/services/chat/test/acceptance/js/GettingMessagesTests.js
@@ -46,9 +46,8 @@ describe('Getting messages', async function () {
})
it('should contain the messages and populated users when getting the messages', async function () {
- const { response, body: messages } = await ChatClient.getGlobalMessages(
- projectId
- )
+ const { response, body: messages } =
+ await ChatClient.getGlobalMessages(projectId)
expect(response.statusCode).to.equal(200)
expect(messages.length).to.equal(2)
messages.reverse()
diff --git a/services/chat/test/acceptance/js/SendingAMessageTests.js b/services/chat/test/acceptance/js/SendingAMessageTests.js
index 27a06780af..7dbc1df3a5 100644
--- a/services/chat/test/acceptance/js/SendingAMessageTests.js
+++ b/services/chat/test/acceptance/js/SendingAMessageTests.js
@@ -26,9 +26,8 @@ describe('Sending a message', async function () {
})
it('should then list the message in the project messages', async function () {
- const { response, body: messages } = await ChatClient.getGlobalMessages(
- projectId
- )
+ const { response, body: messages } =
+ await ChatClient.getGlobalMessages(projectId)
expect(response.statusCode).to.equal(200)
expect(messages.length).to.equal(1)
expect(messages[0].content).to.equal(content)
@@ -61,9 +60,8 @@ describe('Sending a message', async function () {
})
it('should not appear in the global messages', async function () {
- const { response, body: messages } = await ChatClient.getGlobalMessages(
- projectId
- )
+ const { response, body: messages } =
+ await ChatClient.getGlobalMessages(projectId)
expect(response.statusCode).to.equal(200)
expect(messages.length).to.equal(0)
})
diff --git a/services/clsi/app/js/ProjectPersistenceManager.js b/services/clsi/app/js/ProjectPersistenceManager.js
index 52f61840c7..4dbe8b636e 100644
--- a/services/clsi/app/js/ProjectPersistenceManager.js
+++ b/services/clsi/app/js/ProjectPersistenceManager.js
@@ -88,15 +88,18 @@ module.exports = ProjectPersistenceManager = {
})
},
() => {
- setInterval(() => {
- ProjectPersistenceManager.refreshExpiryTimeout(() => {
- ProjectPersistenceManager.clearExpiredProjects(err => {
- if (err) {
- logger.error({ err }, 'clearing expired projects failed')
- }
+ setInterval(
+ () => {
+ ProjectPersistenceManager.refreshExpiryTimeout(() => {
+ ProjectPersistenceManager.clearExpiredProjects(err => {
+ if (err) {
+ logger.error({ err }, 'clearing expired projects failed')
+ }
+ })
})
- })
- }, 10 * 60 * 1000)
+ },
+ 10 * 60 * 1000
+ )
}
)
})
@@ -111,39 +114,38 @@ module.exports = ProjectPersistenceManager = {
if (callback == null) {
callback = function () {}
}
- return ProjectPersistenceManager._findExpiredProjectIds(function (
- error,
- projectIds
- ) {
- if (error != null) {
- return callback(error)
- }
- logger.debug({ projectIds }, 'clearing expired projects')
- const jobs = Array.from(projectIds || []).map(projectId =>
- (
- projectId => callback =>
- ProjectPersistenceManager.clearProjectFromCache(
- projectId,
- { reason: 'expired' },
- function (err) {
- if (err != null) {
- logger.error({ err, projectId }, 'error clearing project')
- }
- return callback()
- }
- )
- )(projectId)
- )
- return async.series(jobs, function (error) {
+ return ProjectPersistenceManager._findExpiredProjectIds(
+ function (error, projectIds) {
if (error != null) {
return callback(error)
}
- return CompileManager.clearExpiredProjects(
- ProjectPersistenceManager.EXPIRY_TIMEOUT,
- error => callback(error)
+ logger.debug({ projectIds }, 'clearing expired projects')
+ const jobs = Array.from(projectIds || []).map(projectId =>
+ (
+ projectId => callback =>
+ ProjectPersistenceManager.clearProjectFromCache(
+ projectId,
+ { reason: 'expired' },
+ function (err) {
+ if (err != null) {
+ logger.error({ err, projectId }, 'error clearing project')
+ }
+ return callback()
+ }
+ )
+ )(projectId)
)
- })
- })
+ return async.series(jobs, function (error) {
+ if (error != null) {
+ return callback(error)
+ }
+ return CompileManager.clearExpiredProjects(
+ ProjectPersistenceManager.EXPIRY_TIMEOUT,
+ error => callback(error)
+ )
+ })
+ }
+ )
}, // ignore any errors from deleting directories
clearProject(projectId, userId, callback) {
diff --git a/services/document-updater/app/js/UpdateManager.js b/services/document-updater/app/js/UpdateManager.js
index a086cb62e4..fc71e74b63 100644
--- a/services/document-updater/app/js/UpdateManager.js
+++ b/services/document-updater/app/js/UpdateManager.js
@@ -74,9 +74,8 @@ const UpdateManager = {
doc_id: docId,
})
- const updates = await RealTimeRedisManager.promises.getPendingUpdatesForDoc(
- docId
- )
+ const updates =
+ await RealTimeRedisManager.promises.getPendingUpdatesForDoc(docId)
logger.debug(
{ projectId, docId, count: updates.length },
'processing updates'
diff --git a/services/document-updater/app/js/sharejs/types/text-tp2.js b/services/document-updater/app/js/sharejs/types/text-tp2.js
index e2a40cf6bc..c3ff9ecf40 100644
--- a/services/document-updater/app/js/sharejs/types/text-tp2.js
+++ b/services/document-updater/app/js/sharejs/types/text-tp2.js
@@ -129,8 +129,8 @@ type._takeDoc = takeDoc = function (
? part.slice(position.offset, position.offset + maxlength)
: part.slice(position.offset)
: maxlength === undefined || tombsIndivisible
- ? part - position.offset
- : Math.min(maxlength, part - position.offset)
+ ? part - position.offset
+ : Math.min(maxlength, part - position.offset)
const resultLen = result.length || result
diff --git a/services/document-updater/test/stress/js/run.js b/services/document-updater/test/stress/js/run.js
index cbf9369ef9..4d2614eac4 100644
--- a/services/document-updater/test/stress/js/run.js
+++ b/services/document-updater/test/stress/js/run.js
@@ -162,9 +162,12 @@ class StressTestClient {
continue() {
if (this.updateCount > 0) {
this.updateCount--
- return setTimeout(() => {
- return this.sendUpdate()
- }, this.options.updateDelay * (0.5 + Math.random()))
+ return setTimeout(
+ () => {
+ return this.sendUpdate()
+ },
+ this.options.updateDelay * (0.5 + Math.random())
+ )
} else {
return this.updateCallback()
}
diff --git a/services/history-v1/storage/lib/blob_hash.js b/services/history-v1/storage/lib/blob_hash.js
index 52dc8cb3e2..5c2edac14f 100644
--- a/services/history-v1/storage/lib/blob_hash.js
+++ b/services/history-v1/storage/lib/blob_hash.js
@@ -26,25 +26,24 @@ function getBlobHash(byteLength) {
* @param {stream.Readable} stream
* @return {Promise.} hexadecimal SHA-1 hash
*/
-exports.fromStream = BPromise.method(function blobHashFromStream(
- byteLength,
- stream
-) {
- assert.integer(byteLength, 'blobHash: bad byteLength')
- assert.object(stream, 'blobHash: bad stream')
+exports.fromStream = BPromise.method(
+ function blobHashFromStream(byteLength, stream) {
+ assert.integer(byteLength, 'blobHash: bad byteLength')
+ assert.object(stream, 'blobHash: bad stream')
- const hash = getBlobHash(byteLength)
- return new BPromise(function (resolve, reject) {
- pipeline(stream, hash, function (err) {
- if (err) {
- reject(err)
- } else {
- hash.end()
- resolve(hash.read())
- }
+ const hash = getBlobHash(byteLength)
+ return new BPromise(function (resolve, reject) {
+ pipeline(stream, hash, function (err) {
+ if (err) {
+ reject(err)
+ } else {
+ hash.end()
+ resolve(hash.read())
+ }
+ })
})
- })
-})
+ }
+)
/**
* Compute the git blob hash for a blob with the given string content.
diff --git a/services/project-history/app/js/ErrorRecorder.js b/services/project-history/app/js/ErrorRecorder.js
index 9530b86857..ab04eee063 100644
--- a/services/project-history/app/js/ErrorRecorder.js
+++ b/services/project-history/app/js/ErrorRecorder.js
@@ -194,111 +194,113 @@ export function getFailures(callback) {
if (callback == null) {
callback = function () {}
}
- return getFailuresByType(function (
- error,
- failureCounts,
- failureAttempts,
- failureRequests,
- maxQueueSize
- ) {
- let attempts, failureType, label, requests
- if (error != null) {
- return callback(OError.tag(error))
+ return getFailuresByType(
+ function (
+ error,
+ failureCounts,
+ failureAttempts,
+ failureRequests,
+ maxQueueSize
+ ) {
+ let attempts, failureType, label, requests
+ if (error != null) {
+ return callback(OError.tag(error))
+ }
+
+ const shortNames = {
+ 'Error: bad response from filestore: 404': 'filestore-404',
+ 'Error: bad response from filestore: 500': 'filestore-500',
+ 'NotFoundError: got a 404 from web api': 'web-api-404',
+ 'Error: history store a non-success status code: 413':
+ 'history-store-413',
+ 'Error: history store a non-success status code: 422':
+ 'history-store-422',
+ 'Error: history store a non-success status code: 500':
+ 'history-store-500',
+ 'Error: history store a non-success status code: 503':
+ 'history-store-503',
+ 'Error: web returned a non-success status code: 500 (attempts: 2)':
+ 'web-500',
+ 'Error: ESOCKETTIMEDOUT': 'socket-timeout',
+ 'Error: no project found': 'no-project-found',
+ 'OpsOutOfOrderError: project structure version out of order on incoming updates':
+ 'incoming-project-version-out-of-order',
+ 'OpsOutOfOrderError: doc version out of order on incoming updates':
+ 'incoming-doc-version-out-of-order',
+ 'OpsOutOfOrderError: project structure version out of order':
+ 'chunk-project-version-out-of-order',
+ 'OpsOutOfOrderError: doc version out of order':
+ 'chunk-doc-version-out-of-order',
+ 'Error: failed to extend lock': 'lock-overrun',
+ 'Error: tried to release timed out lock': 'lock-overrun',
+ 'Error: Timeout': 'lock-overrun',
+ 'Error: sync ongoing': 'sync-ongoing',
+ 'SyncError: unexpected resyncProjectStructure update': 'sync-error',
+ '[object Error]': 'unknown-error-object',
+ 'UpdateWithUnknownFormatError: update with unknown format':
+ 'unknown-format',
+ 'Error: update with unknown format': 'unknown-format',
+ 'TextOperationError: The base length of the second operation has to be the target length of the first operation':
+ 'text-op-error',
+ 'Error: ENOSPC: no space left on device, write': 'ENOSPC',
+ '*': 'other',
+ }
+
+ // set all the known errors to zero if not present (otherwise gauges stay on their last value)
+ const summaryCounts = {}
+ const summaryAttempts = {}
+ const summaryRequests = {}
+ const summaryMaxQueueSize = {}
+
+ for (failureType in shortNames) {
+ label = shortNames[failureType]
+ summaryCounts[label] = 0
+ summaryAttempts[label] = 0
+ summaryRequests[label] = 0
+ summaryMaxQueueSize[label] = 0
+ }
+
+ // record a metric for each type of failure
+ for (failureType in failureCounts) {
+ const failureCount = failureCounts[failureType]
+ label = shortNames[failureType] || shortNames['*']
+ summaryCounts[label] += failureCount
+ summaryAttempts[label] += failureAttempts[failureType]
+ summaryRequests[label] += failureRequests[failureType]
+ summaryMaxQueueSize[label] = Math.max(
+ maxQueueSize[failureType],
+ summaryMaxQueueSize[label]
+ )
+ }
+
+ for (label in summaryCounts) {
+ const count = summaryCounts[label]
+ metrics.globalGauge('failed', count, 1, { status: label })
+ }
+
+ for (label in summaryAttempts) {
+ attempts = summaryAttempts[label]
+ metrics.globalGauge('attempts', attempts, 1, { status: label })
+ }
+
+ for (label in summaryRequests) {
+ requests = summaryRequests[label]
+ metrics.globalGauge('requests', requests, 1, { status: label })
+ }
+
+ for (label in summaryMaxQueueSize) {
+ const queueSize = summaryMaxQueueSize[label]
+ metrics.globalGauge('max-queue-size', queueSize, 1, { status: label })
+ }
+
+ return callback(null, {
+ counts: summaryCounts,
+ attempts: summaryAttempts,
+ requests: summaryRequests,
+ maxQueueSize: summaryMaxQueueSize,
+ })
}
-
- const shortNames = {
- 'Error: bad response from filestore: 404': 'filestore-404',
- 'Error: bad response from filestore: 500': 'filestore-500',
- 'NotFoundError: got a 404 from web api': 'web-api-404',
- 'Error: history store a non-success status code: 413':
- 'history-store-413',
- 'Error: history store a non-success status code: 422':
- 'history-store-422',
- 'Error: history store a non-success status code: 500':
- 'history-store-500',
- 'Error: history store a non-success status code: 503':
- 'history-store-503',
- 'Error: web returned a non-success status code: 500 (attempts: 2)':
- 'web-500',
- 'Error: ESOCKETTIMEDOUT': 'socket-timeout',
- 'Error: no project found': 'no-project-found',
- 'OpsOutOfOrderError: project structure version out of order on incoming updates':
- 'incoming-project-version-out-of-order',
- 'OpsOutOfOrderError: doc version out of order on incoming updates':
- 'incoming-doc-version-out-of-order',
- 'OpsOutOfOrderError: project structure version out of order':
- 'chunk-project-version-out-of-order',
- 'OpsOutOfOrderError: doc version out of order':
- 'chunk-doc-version-out-of-order',
- 'Error: failed to extend lock': 'lock-overrun',
- 'Error: tried to release timed out lock': 'lock-overrun',
- 'Error: Timeout': 'lock-overrun',
- 'Error: sync ongoing': 'sync-ongoing',
- 'SyncError: unexpected resyncProjectStructure update': 'sync-error',
- '[object Error]': 'unknown-error-object',
- 'UpdateWithUnknownFormatError: update with unknown format':
- 'unknown-format',
- 'Error: update with unknown format': 'unknown-format',
- 'TextOperationError: The base length of the second operation has to be the target length of the first operation':
- 'text-op-error',
- 'Error: ENOSPC: no space left on device, write': 'ENOSPC',
- '*': 'other',
- }
-
- // set all the known errors to zero if not present (otherwise gauges stay on their last value)
- const summaryCounts = {}
- const summaryAttempts = {}
- const summaryRequests = {}
- const summaryMaxQueueSize = {}
-
- for (failureType in shortNames) {
- label = shortNames[failureType]
- summaryCounts[label] = 0
- summaryAttempts[label] = 0
- summaryRequests[label] = 0
- summaryMaxQueueSize[label] = 0
- }
-
- // record a metric for each type of failure
- for (failureType in failureCounts) {
- const failureCount = failureCounts[failureType]
- label = shortNames[failureType] || shortNames['*']
- summaryCounts[label] += failureCount
- summaryAttempts[label] += failureAttempts[failureType]
- summaryRequests[label] += failureRequests[failureType]
- summaryMaxQueueSize[label] = Math.max(
- maxQueueSize[failureType],
- summaryMaxQueueSize[label]
- )
- }
-
- for (label in summaryCounts) {
- const count = summaryCounts[label]
- metrics.globalGauge('failed', count, 1, { status: label })
- }
-
- for (label in summaryAttempts) {
- attempts = summaryAttempts[label]
- metrics.globalGauge('attempts', attempts, 1, { status: label })
- }
-
- for (label in summaryRequests) {
- requests = summaryRequests[label]
- metrics.globalGauge('requests', requests, 1, { status: label })
- }
-
- for (label in summaryMaxQueueSize) {
- const queueSize = summaryMaxQueueSize[label]
- metrics.globalGauge('max-queue-size', queueSize, 1, { status: label })
- }
-
- return callback(null, {
- counts: summaryCounts,
- attempts: summaryAttempts,
- requests: summaryRequests,
- maxQueueSize: summaryMaxQueueSize,
- })
- })
+ )
}
export const promises = {
diff --git a/services/project-history/app/js/FlushManager.js b/services/project-history/app/js/FlushManager.js
index c8e413d56c..7f8514afc0 100644
--- a/services/project-history/app/js/FlushManager.js
+++ b/services/project-history/app/js/FlushManager.js
@@ -59,79 +59,81 @@ export function flushOldOps(options, callback) {
if (error != null) {
return callback(OError.tag(error))
}
- return ErrorRecorder.getFailedProjects(function (
- error,
- projectHistoryFailures
- ) {
- if (error != null) {
- return callback(OError.tag(error))
- }
- // exclude failed projects already in projectHistoryFailures
- const failedProjects = new Set()
- for (const entry of Array.from(projectHistoryFailures)) {
- failedProjects.add(entry.project_id)
- }
- // randomise order so we get different projects if there is a limit
- projectIds = _.shuffle(projectIds)
- const maxAge = options.maxAge || 6 * 3600 // default to 6 hours
- const cutoffTime = new Date(Date.now() - maxAge * 1000)
- const startTime = new Date()
- let count = 0
- const jobs = projectIds.map(
- projectId =>
- function (cb) {
- const timeTaken = new Date() - startTime
- count++
- if (
- (options != null ? options.timeout : undefined) &&
- timeTaken > options.timeout
- ) {
- // finish early due to timeout, return an error to bail out of the async iteration
- logger.debug('background retries timed out')
- return cb(new OError('retries timed out'))
- }
- if (
- (options != null ? options.limit : undefined) &&
- count > options.limit
- ) {
- // finish early due to reaching limit, return an error to bail out of the async iteration
- logger.debug({ count }, 'background retries hit limit')
- return cb(new OError('hit limit'))
- }
- if (failedProjects.has(projectId)) {
- // skip failed projects
- return setTimeout(cb, options.queueDelay || 100) // pause between flushes
- }
- return flushIfOld(projectId, cutoffTime, function (err) {
- if (err != null) {
- logger.warn(
- { projectId, flushErr: err },
- 'error flushing old project'
- )
+ return ErrorRecorder.getFailedProjects(
+ function (error, projectHistoryFailures) {
+ if (error != null) {
+ return callback(OError.tag(error))
+ }
+ // exclude failed projects already in projectHistoryFailures
+ const failedProjects = new Set()
+ for (const entry of Array.from(projectHistoryFailures)) {
+ failedProjects.add(entry.project_id)
+ }
+ // randomise order so we get different projects if there is a limit
+ projectIds = _.shuffle(projectIds)
+ const maxAge = options.maxAge || 6 * 3600 // default to 6 hours
+ const cutoffTime = new Date(Date.now() - maxAge * 1000)
+ const startTime = new Date()
+ let count = 0
+ const jobs = projectIds.map(
+ projectId =>
+ function (cb) {
+ const timeTaken = new Date() - startTime
+ count++
+ if (
+ (options != null ? options.timeout : undefined) &&
+ timeTaken > options.timeout
+ ) {
+ // finish early due to timeout, return an error to bail out of the async iteration
+ logger.debug('background retries timed out')
+ return cb(new OError('retries timed out'))
+ }
+ if (
+ (options != null ? options.limit : undefined) &&
+ count > options.limit
+ ) {
+ // finish early due to reaching limit, return an error to bail out of the async iteration
+ logger.debug({ count }, 'background retries hit limit')
+ return cb(new OError('hit limit'))
+ }
+ if (failedProjects.has(projectId)) {
+ // skip failed projects
+ return setTimeout(cb, options.queueDelay || 100) // pause between flushes
+ }
+ return flushIfOld(projectId, cutoffTime, function (err) {
+ if (err != null) {
+ logger.warn(
+ { projectId, flushErr: err },
+ 'error flushing old project'
+ )
+ }
+ return setTimeout(cb, options.queueDelay || 100)
+ })
+ }
+ ) // pause between flushes
+ return async.series(
+ async.reflectAll(jobs),
+ function (error, results) {
+ const success = []
+ const failure = []
+ results.forEach((result, i) => {
+ if (
+ result.error != null &&
+ !['retries timed out', 'hit limit'].includes(
+ result?.error?.message
+ )
+ ) {
+ // ignore expected errors
+ return failure.push(projectIds[i])
+ } else {
+ return success.push(projectIds[i])
}
- return setTimeout(cb, options.queueDelay || 100)
})
+ return callback(error, { success, failure, failedProjects })
}
- ) // pause between flushes
- return async.series(async.reflectAll(jobs), function (error, results) {
- const success = []
- const failure = []
- results.forEach((result, i) => {
- if (
- result.error != null &&
- !['retries timed out', 'hit limit'].includes(
- result?.error?.message
- )
- ) {
- // ignore expected errors
- return failure.push(projectIds[i])
- } else {
- return success.push(projectIds[i])
- }
- })
- return callback(error, { success, failure, failedProjects })
- })
- })
+ )
+ }
+ )
}
)
}
diff --git a/services/project-history/app/js/RetryManager.js b/services/project-history/app/js/RetryManager.js
index 4acefa5ea2..5c52931000 100644
--- a/services/project-history/app/js/RetryManager.js
+++ b/services/project-history/app/js/RetryManager.js
@@ -175,9 +175,8 @@ async function checkProjectHasHistoryId(projectId) {
async function waitUntilRedisQueueIsEmpty(projectId) {
for (let attempts = 0; attempts < 30; attempts++) {
- const updatesCount = await RedisManager.promises.countUnprocessedUpdates(
- projectId
- )
+ const updatesCount =
+ await RedisManager.promises.countUnprocessedUpdates(projectId)
if (updatesCount === 0) {
return
}
diff --git a/services/project-history/app/js/UpdateCompressor.js b/services/project-history/app/js/UpdateCompressor.js
index 7d801a0cd7..d6d6867b1d 100644
--- a/services/project-history/app/js/UpdateCompressor.js
+++ b/services/project-history/app/js/UpdateCompressor.js
@@ -252,12 +252,12 @@ function _concatTwoUpdates(firstUpdate, secondUpdate) {
firstOp.p === secondOp.p
) {
offset = firstOp.p
- const diffUpdates = diffAsShareJsOps(firstOp.d, secondOp.i).map(function (
- op
- ) {
- op.p += offset
- return mergeUpdatesWithOp(firstUpdate, secondUpdate, op)
- })
+ const diffUpdates = diffAsShareJsOps(firstOp.d, secondOp.i).map(
+ function (op) {
+ op.p += offset
+ return mergeUpdatesWithOp(firstUpdate, secondUpdate, op)
+ }
+ )
// Doing a diff like this loses track of the doc lengths for each
// update, so recalculate them
diff --git a/services/project-history/scripts/clear_dangling_timestamps.js b/services/project-history/scripts/clear_dangling_timestamps.js
index 8779006495..e83eb1d7fa 100644
--- a/services/project-history/scripts/clear_dangling_timestamps.js
+++ b/services/project-history/scripts/clear_dangling_timestamps.js
@@ -25,9 +25,8 @@ async function main() {
let clearedTimestamps = 0
let processed = 0
for (const projectId of projectIdsWithFirstOpTimestamps) {
- const result = await RedisManager.promises.clearDanglingFirstOpTimestamp(
- projectId
- )
+ const result =
+ await RedisManager.promises.clearDanglingFirstOpTimestamp(projectId)
processed++
clearedTimestamps += result
if (processed % 1000 === 0) {
diff --git a/services/real-time/app/js/RedisClientManager.js b/services/real-time/app/js/RedisClientManager.js
index d818f43a05..63eccef106 100644
--- a/services/real-time/app/js/RedisClientManager.js
+++ b/services/real-time/app/js/RedisClientManager.js
@@ -8,10 +8,10 @@ module.exports = {
const redisType = x.cluster
? 'cluster'
: x.sentinels
- ? 'sentinel'
- : x.host
- ? 'single'
- : 'unknown'
+ ? 'sentinel'
+ : x.host
+ ? 'single'
+ : 'unknown'
logger.debug({ redis: redisType }, 'creating redis client')
return redis.createClient(x)
})
diff --git a/services/web/app/src/Features/Authentication/AuthenticationManager.js b/services/web/app/src/Features/Authentication/AuthenticationManager.js
index 937e1d67b1..3d1b491f3a 100644
--- a/services/web/app/src/Features/Authentication/AuthenticationManager.js
+++ b/services/web/app/src/Features/Authentication/AuthenticationManager.js
@@ -166,9 +166,8 @@ const AuthenticationManager = {
let isPasswordReused
try {
- isPasswordReused = await HaveIBeenPwned.promises.checkPasswordForReuse(
- password
- )
+ isPasswordReused =
+ await HaveIBeenPwned.promises.checkPasswordForReuse(password)
} catch (err) {
logger.err({ err }, 'cannot check password for re-use')
}
@@ -333,9 +332,8 @@ const AuthenticationManager = {
let isPasswordReused
try {
- isPasswordReused = await HaveIBeenPwned.promises.checkPasswordForReuse(
- password
- )
+ isPasswordReused =
+ await HaveIBeenPwned.promises.checkPasswordForReuse(password)
} catch (error) {
logger.err({ error }, 'cannot check password for re-use')
}
diff --git a/services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js b/services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js
index 3546972099..cc457d7309 100644
--- a/services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js
+++ b/services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js
@@ -34,9 +34,8 @@ const CollaboratorsInviteController = {
async getAllInvites(req, res) {
const projectId = req.params.Project_id
logger.debug({ projectId }, 'getting all active invites for project')
- const invites = await CollaboratorsInviteHandler.promises.getAllInvites(
- projectId
- )
+ const invites =
+ await CollaboratorsInviteHandler.promises.getAllInvites(projectId)
res.json({ invites })
},
@@ -115,9 +114,8 @@ const CollaboratorsInviteController = {
return res.status(400).json({ errorReason: 'invalid_email' })
}
- const underRateLimit = await CollaboratorsInviteController._checkRateLimit(
- sendingUserId
- )
+ const underRateLimit =
+ await CollaboratorsInviteController._checkRateLimit(sendingUserId)
if (!underRateLimit) {
return res.sendStatus(429)
}
diff --git a/services/web/app/src/Features/Editor/EditorHttpController.js b/services/web/app/src/Features/Editor/EditorHttpController.js
index bd0ca113ea..6e820c2fe4 100644
--- a/services/web/app/src/Features/Editor/EditorHttpController.js
+++ b/services/web/app/src/Features/Editor/EditorHttpController.js
@@ -152,17 +152,15 @@ async function joinProject(req, res, next) {
}
async function _buildJoinProjectView(req, projectId, userId) {
- const project = await ProjectGetter.promises.getProjectWithoutDocLines(
- projectId
- )
+ const project =
+ await ProjectGetter.promises.getProjectWithoutDocLines(projectId)
if (project == null) {
throw new Errors.NotFoundError('project not found')
}
let deletedDocsFromDocstore = []
try {
- deletedDocsFromDocstore = await DocstoreManager.promises.getAllDeletedDocs(
- projectId
- )
+ deletedDocsFromDocstore =
+ await DocstoreManager.promises.getAllDeletedDocs(projectId)
} catch (err) {
// The query in docstore is not optimized at this time and fails for
// projects with many very large, deleted documents.
@@ -187,9 +185,8 @@ async function _buildJoinProjectView(req, projectId, userId) {
if (privilegeLevel == null || privilegeLevel === PrivilegeLevels.NONE) {
return { project: null, privilegeLevel: null, isRestrictedUser: false }
}
- const invites = await CollaboratorsInviteHandler.promises.getAllInvites(
- projectId
- )
+ const invites =
+ await CollaboratorsInviteHandler.promises.getAllInvites(projectId)
const isTokenMember = await CollaboratorsHandler.promises.userIsTokenMember(
userId,
projectId
diff --git a/services/web/app/src/Features/Email/Layouts/BaseWithHeaderEmailLayout.js b/services/web/app/src/Features/Email/Layouts/BaseWithHeaderEmailLayout.js
index 9be1b73595..11546e74c0 100644
--- a/services/web/app/src/Features/Email/Layouts/BaseWithHeaderEmailLayout.js
+++ b/services/web/app/src/Features/Email/Layouts/BaseWithHeaderEmailLayout.js
@@ -375,10 +375,10 @@ module.exports = _.template(`\
? `${settings.email.template.customFooter}
`
: ''
}${settings.appName} • ${
- settings.siteUrl
-}
+ settings.siteUrl
+ }" style="Margin: 0; color: #0F7A06; font-family: Helvetica, Arial, sans-serif; font-weight: normal; line-height: 1.3; margin: 0; padding: 0; text-align: left; text-decoration: none;">${
+ settings.siteUrl
+ }
diff --git a/services/web/app/src/Features/History/HistoryManager.js b/services/web/app/src/Features/History/HistoryManager.js
index e1f20f1a8d..b59ba5e8dd 100644
--- a/services/web/app/src/Features/History/HistoryManager.js
+++ b/services/web/app/src/Features/History/HistoryManager.js
@@ -138,8 +138,8 @@ async function injectUserDetails(data) {
const entries = Array.isArray(data.diff)
? data.diff
: Array.isArray(data.updates)
- ? data.updates
- : []
+ ? data.updates
+ : []
for (const entry of entries) {
for (const user of (entry.meta && entry.meta.users) || []) {
if (typeof user === 'string') {
diff --git a/services/web/app/src/Features/Institutions/InstitutionsManager.js b/services/web/app/src/Features/Institutions/InstitutionsManager.js
index f7c1fc6c52..116837c7d8 100644
--- a/services/web/app/src/Features/Institutions/InstitutionsManager.js
+++ b/services/web/app/src/Features/Institutions/InstitutionsManager.js
@@ -105,9 +105,8 @@ const InstitutionsManager = {
async refreshInstitutionUsers(institutionId, notify) {
const refreshFunction = notify ? refreshFeaturesAndNotify : refreshFeatures
- const { institution, affiliations } = await fetchInstitutionAndAffiliations(
- institutionId
- )
+ const { institution, affiliations } =
+ await fetchInstitutionAndAffiliations(institutionId)
for (const affiliation of affiliations) {
affiliation.institutionName = institution.name
@@ -316,9 +315,8 @@ async function refreshFeaturesAndNotify(affiliation) {
const getUserInfo = async userId => {
const user = await UserGetter.promises.getUser(userId, { _id: 1 })
- const subscription = await SubscriptionLocator.promises.getUsersSubscription(
- user
- )
+ const subscription =
+ await SubscriptionLocator.promises.getUsersSubscription(user)
return { user, subscription }
}
diff --git a/services/web/app/src/Features/PasswordReset/PasswordResetController.js b/services/web/app/src/Features/PasswordReset/PasswordResetController.js
index 739217b997..f9ea0cc7a7 100644
--- a/services/web/app/src/Features/PasswordReset/PasswordResetController.js
+++ b/services/web/app/src/Features/PasswordReset/PasswordResetController.js
@@ -114,9 +114,8 @@ async function requestReset(req, res, next) {
let status
try {
- status = await PasswordResetHandler.promises.generateAndEmailResetToken(
- email
- )
+ status =
+ await PasswordResetHandler.promises.generateAndEmailResetToken(email)
} catch (err) {
OError.tag(err, 'failed to generate and email password reset token', {
email,
diff --git a/services/web/app/src/Features/Project/ProjectController.js b/services/web/app/src/Features/Project/ProjectController.js
index 4ba5fad2c5..dc2e054d71 100644
--- a/services/web/app/src/Features/Project/ProjectController.js
+++ b/services/web/app/src/Features/Project/ProjectController.js
@@ -751,8 +751,8 @@ const ProjectController = {
? // TODO: Create React version of detached page
'project/editor_detached'
: idePageReact
- ? 'project/ide-react'
- : 'project/editor'
+ ? 'project/ide-react'
+ : 'project/editor'
res.render(template, {
title: project.name,
diff --git a/services/web/app/src/Features/Project/ProjectDeleter.js b/services/web/app/src/Features/Project/ProjectDeleter.js
index 91b742befb..5e8df133bd 100644
--- a/services/web/app/src/Features/Project/ProjectDeleter.js
+++ b/services/web/app/src/Features/Project/ProjectDeleter.js
@@ -418,9 +418,8 @@ let deletedFilesProjectIdIndexExist
async function doesDeletedFilesProjectIdIndexExist() {
if (typeof deletedFilesProjectIdIndexExist !== 'boolean') {
// Resolve this about once. No need for locking or retry handling.
- deletedFilesProjectIdIndexExist = await db.deletedFiles.indexExists(
- 'projectId_1'
- )
+ deletedFilesProjectIdIndexExist =
+ await db.deletedFiles.indexExists('projectId_1')
}
return deletedFilesProjectIdIndexExist
}
diff --git a/services/web/app/src/Features/Project/ProjectEntityMongoUpdateHandler.js b/services/web/app/src/Features/Project/ProjectEntityMongoUpdateHandler.js
index baf7cf047c..cf543a3a4e 100644
--- a/services/web/app/src/Features/Project/ProjectEntityMongoUpdateHandler.js
+++ b/services/web/app/src/Features/Project/ProjectEntityMongoUpdateHandler.js
@@ -265,9 +265,8 @@ async function mkdirp(projectId, path, options = {}) {
// to make matching case-sensitive
const folders = path.split('/').filter(folder => folder.length !== 0)
- const project = await ProjectGetter.promises.getProjectWithOnlyFolders(
- projectId
- )
+ const project =
+ await ProjectGetter.promises.getProjectWithOnlyFolders(projectId)
if (path === '/') {
return { newFolders: [], folder: project.rootFolder[0] }
}
diff --git a/services/web/app/src/Features/Project/ProjectEntityUpdateHandler.js b/services/web/app/src/Features/Project/ProjectEntityUpdateHandler.js
index 9e7b52460a..a332397b11 100644
--- a/services/web/app/src/Features/Project/ProjectEntityUpdateHandler.js
+++ b/services/web/app/src/Features/Project/ProjectEntityUpdateHandler.js
@@ -645,153 +645,159 @@ const ProjectEntityUpdateHandler = {
)
},
- upsertDoc: wrapWithLock(function (
- projectId,
- folderId,
- docName,
- docLines,
- source,
- userId,
- callback
- ) {
- if (!SafePath.isCleanFilename(docName)) {
- return callback(new Errors.InvalidNameError('invalid element name'))
- }
- ProjectLocator.findElement(
- { project_id: projectId, element_id: folderId, type: 'folder' },
- (error, folder, folderPath) => {
- if (error != null) {
- if (error instanceof Errors.NotFoundError && folder == null) {
- return callback(new Error('folder_not_found'))
- }
- return callback(error)
- }
- if (folder == null) {
- return callback(new Error("Couldn't find folder"))
- }
- const existingDoc = folder.docs.find(({ name }) => name === docName)
- const existingFile = folder.fileRefs.find(
- ({ name }) => name === docName
- )
- if (existingFile) {
- const doc = new Doc({ name: docName })
- const filePath = `${folderPath.fileSystem}/${existingFile.name}`
- DocstoreManager.updateDoc(
- projectId.toString(),
- doc._id.toString(),
- docLines,
- 0,
- {},
- (err, modified, rev) => {
- if (err != null) {
- return callback(err)
- }
- doc.rev = rev
- ProjectEntityMongoUpdateHandler.replaceFileWithDoc(
- projectId,
- existingFile._id,
- doc,
- (err, project) => {
- if (err) {
- return callback(err)
- }
- TpdsUpdateSender.addDoc(
- {
- projectId,
- docId: doc._id,
- path: filePath,
- projectName: project.name,
- rev: existingFile.rev + 1,
- folderId,
- },
- err => {
- if (err) {
- return callback(err)
- }
- const projectHistoryId =
- project.overleaf &&
- project.overleaf.history &&
- project.overleaf.history.id
- const newDocs = [
- {
- doc,
- path: filePath,
- docLines: docLines.join('\n'),
- },
- ]
- const oldFiles = [
- {
- file: existingFile,
- path: filePath,
- },
- ]
- DocumentUpdaterHandler.updateProjectStructure(
- projectId,
- projectHistoryId,
- userId,
- { oldFiles, newDocs, newProject: project },
- source,
- error => {
- if (error != null) {
- return callback(error)
- }
- EditorRealTimeController.emitToRoom(
- projectId,
- 'removeEntity',
- existingFile._id,
- 'convertFileToDoc'
- )
- callback(null, doc, true)
- }
- )
- }
- )
- }
- )
- }
- )
- } else if (existingDoc) {
- DocumentUpdaterHandler.setDocument(
- projectId,
- existingDoc._id,
- userId,
- docLines,
- source,
- (err, result) => {
- if (err != null) {
- return callback(err)
- }
- logger.debug(
- { projectId, docId: existingDoc._id },
- 'notifying users that the document has been updated'
- )
- // there is no need to flush the doc to mongo at this point as docupdater
- // flushes it as part of setDoc.
- //
- // combine rev from response with existing doc metadata
- callback(null, { ...existingDoc, ...result }, existingDoc == null)
- }
- )
- } else {
- ProjectEntityUpdateHandler.addDocWithRanges.withoutLock(
- projectId,
- folderId,
- docName,
- docLines,
- {},
- userId,
- source,
- (err, doc) => {
- if (err != null) {
- return callback(err)
- }
- callback(null, doc, existingDoc == null)
- }
- )
- }
+ upsertDoc: wrapWithLock(
+ function (
+ projectId,
+ folderId,
+ docName,
+ docLines,
+ source,
+ userId,
+ callback
+ ) {
+ if (!SafePath.isCleanFilename(docName)) {
+ return callback(new Errors.InvalidNameError('invalid element name'))
}
- )
- }),
+ ProjectLocator.findElement(
+ { project_id: projectId, element_id: folderId, type: 'folder' },
+ (error, folder, folderPath) => {
+ if (error != null) {
+ if (error instanceof Errors.NotFoundError && folder == null) {
+ return callback(new Error('folder_not_found'))
+ }
+ return callback(error)
+ }
+ if (folder == null) {
+ return callback(new Error("Couldn't find folder"))
+ }
+ const existingDoc = folder.docs.find(({ name }) => name === docName)
+ const existingFile = folder.fileRefs.find(
+ ({ name }) => name === docName
+ )
+ if (existingFile) {
+ const doc = new Doc({ name: docName })
+ const filePath = `${folderPath.fileSystem}/${existingFile.name}`
+ DocstoreManager.updateDoc(
+ projectId.toString(),
+ doc._id.toString(),
+ docLines,
+ 0,
+ {},
+ (err, modified, rev) => {
+ if (err != null) {
+ return callback(err)
+ }
+ doc.rev = rev
+ ProjectEntityMongoUpdateHandler.replaceFileWithDoc(
+ projectId,
+ existingFile._id,
+ doc,
+ (err, project) => {
+ if (err) {
+ return callback(err)
+ }
+ TpdsUpdateSender.addDoc(
+ {
+ projectId,
+ docId: doc._id,
+ path: filePath,
+ projectName: project.name,
+ rev: existingFile.rev + 1,
+ folderId,
+ },
+ err => {
+ if (err) {
+ return callback(err)
+ }
+ const projectHistoryId =
+ project.overleaf &&
+ project.overleaf.history &&
+ project.overleaf.history.id
+ const newDocs = [
+ {
+ doc,
+ path: filePath,
+ docLines: docLines.join('\n'),
+ },
+ ]
+ const oldFiles = [
+ {
+ file: existingFile,
+ path: filePath,
+ },
+ ]
+ DocumentUpdaterHandler.updateProjectStructure(
+ projectId,
+ projectHistoryId,
+ userId,
+ { oldFiles, newDocs, newProject: project },
+ source,
+ error => {
+ if (error != null) {
+ return callback(error)
+ }
+ EditorRealTimeController.emitToRoom(
+ projectId,
+ 'removeEntity',
+ existingFile._id,
+ 'convertFileToDoc'
+ )
+ callback(null, doc, true)
+ }
+ )
+ }
+ )
+ }
+ )
+ }
+ )
+ } else if (existingDoc) {
+ DocumentUpdaterHandler.setDocument(
+ projectId,
+ existingDoc._id,
+ userId,
+ docLines,
+ source,
+ (err, result) => {
+ if (err != null) {
+ return callback(err)
+ }
+ logger.debug(
+ { projectId, docId: existingDoc._id },
+ 'notifying users that the document has been updated'
+ )
+ // there is no need to flush the doc to mongo at this point as docupdater
+ // flushes it as part of setDoc.
+ //
+ // combine rev from response with existing doc metadata
+ callback(
+ null,
+ { ...existingDoc, ...result },
+ existingDoc == null
+ )
+ }
+ )
+ } else {
+ ProjectEntityUpdateHandler.addDocWithRanges.withoutLock(
+ projectId,
+ folderId,
+ docName,
+ docLines,
+ {},
+ userId,
+ source,
+ (err, doc) => {
+ if (err != null) {
+ return callback(err)
+ }
+ callback(null, doc, existingDoc == null)
+ }
+ )
+ }
+ }
+ )
+ }
+ ),
upsertFile: wrapWithLock({
beforeLock(next) {
@@ -983,43 +989,38 @@ const ProjectEntityUpdateHandler = {
},
}),
- upsertDocWithPath: wrapWithLock(function (
- projectId,
- elementPath,
- docLines,
- source,
- userId,
- callback
- ) {
- if (!SafePath.isCleanPath(elementPath)) {
- return callback(new Errors.InvalidNameError('invalid element name'))
- }
- const docName = Path.basename(elementPath)
- const folderPath = Path.dirname(elementPath)
- ProjectEntityUpdateHandler.mkdirp.withoutLock(
- projectId,
- folderPath,
- (err, newFolders, folder) => {
- if (err != null) {
- return callback(err)
- }
- ProjectEntityUpdateHandler.upsertDoc.withoutLock(
- projectId,
- folder._id,
- docName,
- docLines,
- source,
- userId,
- (err, doc, isNewDoc) => {
- if (err != null) {
- return callback(err)
- }
- callback(null, doc, isNewDoc, newFolders, folder)
- }
- )
+ upsertDocWithPath: wrapWithLock(
+ function (projectId, elementPath, docLines, source, userId, callback) {
+ if (!SafePath.isCleanPath(elementPath)) {
+ return callback(new Errors.InvalidNameError('invalid element name'))
}
- )
- }),
+ const docName = Path.basename(elementPath)
+ const folderPath = Path.dirname(elementPath)
+ ProjectEntityUpdateHandler.mkdirp.withoutLock(
+ projectId,
+ folderPath,
+ (err, newFolders, folder) => {
+ if (err != null) {
+ return callback(err)
+ }
+ ProjectEntityUpdateHandler.upsertDoc.withoutLock(
+ projectId,
+ folder._id,
+ docName,
+ docLines,
+ source,
+ userId,
+ (err, doc, isNewDoc) => {
+ if (err != null) {
+ return callback(err)
+ }
+ callback(null, doc, isNewDoc, newFolders, folder)
+ }
+ )
+ }
+ )
+ }
+ ),
upsertFileWithPath: wrapWithLock({
beforeLock(next) {
@@ -1115,64 +1116,62 @@ const ProjectEntityUpdateHandler = {
},
}),
- deleteEntity: wrapWithLock(function (
- projectId,
- entityId,
- entityType,
- userId,
- source,
- callback
- ) {
- logger.debug({ entityId, entityType, projectId }, 'deleting project entity')
- if (entityType == null) {
- logger.warn({ err: 'No entityType set', projectId, entityId })
- return callback(new Error('No entityType set'))
- }
- entityType = entityType.toLowerCase()
- ProjectEntityMongoUpdateHandler.deleteEntity(
- projectId,
- entityId,
- entityType,
- (error, entity, path, projectBeforeDeletion, newProject) => {
- if (error != null) {
- return callback(error)
- }
- ProjectEntityUpdateHandler._cleanUpEntity(
- projectBeforeDeletion,
- newProject,
- entity,
- entityType,
- path.fileSystem,
- userId,
- source,
- (error, subtreeListing) => {
- if (error != null) {
- return callback(error)
- }
- const subtreeEntityIds = subtreeListing.map(entry =>
- entry.entity._id.toString()
- )
- TpdsUpdateSender.deleteEntity(
- {
- projectId,
- path: path.fileSystem,
- projectName: projectBeforeDeletion.name,
- entityId,
- entityType,
- subtreeEntityIds,
- },
- error => {
- if (error != null) {
- return callback(error)
- }
- callback(null, entityId)
- }
- )
- }
- )
+ deleteEntity: wrapWithLock(
+ function (projectId, entityId, entityType, userId, source, callback) {
+ logger.debug(
+ { entityId, entityType, projectId },
+ 'deleting project entity'
+ )
+ if (entityType == null) {
+ logger.warn({ err: 'No entityType set', projectId, entityId })
+ return callback(new Error('No entityType set'))
}
- )
- }),
+ entityType = entityType.toLowerCase()
+ ProjectEntityMongoUpdateHandler.deleteEntity(
+ projectId,
+ entityId,
+ entityType,
+ (error, entity, path, projectBeforeDeletion, newProject) => {
+ if (error != null) {
+ return callback(error)
+ }
+ ProjectEntityUpdateHandler._cleanUpEntity(
+ projectBeforeDeletion,
+ newProject,
+ entity,
+ entityType,
+ path.fileSystem,
+ userId,
+ source,
+ (error, subtreeListing) => {
+ if (error != null) {
+ return callback(error)
+ }
+ const subtreeEntityIds = subtreeListing.map(entry =>
+ entry.entity._id.toString()
+ )
+ TpdsUpdateSender.deleteEntity(
+ {
+ projectId,
+ path: path.fileSystem,
+ projectName: projectBeforeDeletion.name,
+ entityId,
+ entityType,
+ subtreeEntityIds,
+ },
+ error => {
+ if (error != null) {
+ return callback(error)
+ }
+ callback(null, entityId)
+ }
+ )
+ }
+ )
+ }
+ )
+ }
+ ),
deleteEntityWithPath: wrapWithLock(
(projectId, path, userId, source, callback) =>
@@ -1225,166 +1224,167 @@ const ProjectEntityUpdateHandler = {
)
}),
- addFolder: wrapWithLock(function (
- projectId,
- parentFolderId,
- folderName,
- callback
- ) {
- if (!SafePath.isCleanFilename(folderName)) {
- return callback(new Errors.InvalidNameError('invalid element name'))
+ addFolder: wrapWithLock(
+ function (projectId, parentFolderId, folderName, callback) {
+ if (!SafePath.isCleanFilename(folderName)) {
+ return callback(new Errors.InvalidNameError('invalid element name'))
+ }
+ ProjectEntityMongoUpdateHandler.addFolder(
+ projectId,
+ parentFolderId,
+ folderName,
+ callback
+ )
}
- ProjectEntityMongoUpdateHandler.addFolder(
+ ),
+
+ moveEntity: wrapWithLock(
+ function (
projectId,
- parentFolderId,
- folderName,
+ entityId,
+ destFolderId,
+ entityType,
+ userId,
+ source,
callback
- )
- }),
-
- moveEntity: wrapWithLock(function (
- projectId,
- entityId,
- destFolderId,
- entityType,
- userId,
- source,
- callback
- ) {
- logger.debug(
- { entityType, entityId, projectId, destFolderId },
- 'moving entity'
- )
- if (entityType == null) {
- logger.warn({ err: 'No entityType set', projectId, entityId })
- return callback(new Error('No entityType set'))
- }
- entityType = entityType.toLowerCase()
- DocumentUpdaterHandler.flushProjectToMongo(projectId, err => {
- if (err) {
- return callback(err)
- }
- ProjectEntityMongoUpdateHandler.moveEntity(
- projectId,
- entityId,
- destFolderId,
- entityType,
- (err, project, startPath, endPath, rev, changes) => {
- if (err != null) {
- return callback(err)
- }
- const projectHistoryId =
- project.overleaf &&
- project.overleaf.history &&
- project.overleaf.history.id
- TpdsUpdateSender.moveEntity(
- {
- projectId,
- projectName: project.name,
- startPath,
- endPath,
- rev,
- entityId,
- entityType,
- folderId: destFolderId,
- },
- err => {
- if (err) {
- logger.error({ err }, 'error sending tpds update')
- }
- DocumentUpdaterHandler.updateProjectStructure(
- projectId,
- projectHistoryId,
- userId,
- changes,
- source,
- callback
- )
- }
- )
- }
+ ) {
+ logger.debug(
+ { entityType, entityId, projectId, destFolderId },
+ 'moving entity'
)
- })
- }),
-
- renameEntity: wrapWithLock(function (
- projectId,
- entityId,
- entityType,
- newName,
- userId,
- source,
- callback
- ) {
- if (!newName || typeof newName !== 'string') {
- const err = new OError('invalid newName value', {
- value: newName,
- type: typeof newName,
- projectId,
- entityId,
- entityType,
- userId,
- source,
+ if (entityType == null) {
+ logger.warn({ err: 'No entityType set', projectId, entityId })
+ return callback(new Error('No entityType set'))
+ }
+ entityType = entityType.toLowerCase()
+ DocumentUpdaterHandler.flushProjectToMongo(projectId, err => {
+ if (err) {
+ return callback(err)
+ }
+ ProjectEntityMongoUpdateHandler.moveEntity(
+ projectId,
+ entityId,
+ destFolderId,
+ entityType,
+ (err, project, startPath, endPath, rev, changes) => {
+ if (err != null) {
+ return callback(err)
+ }
+ const projectHistoryId =
+ project.overleaf &&
+ project.overleaf.history &&
+ project.overleaf.history.id
+ TpdsUpdateSender.moveEntity(
+ {
+ projectId,
+ projectName: project.name,
+ startPath,
+ endPath,
+ rev,
+ entityId,
+ entityType,
+ folderId: destFolderId,
+ },
+ err => {
+ if (err) {
+ logger.error({ err }, 'error sending tpds update')
+ }
+ DocumentUpdaterHandler.updateProjectStructure(
+ projectId,
+ projectHistoryId,
+ userId,
+ changes,
+ source,
+ callback
+ )
+ }
+ )
+ }
+ )
})
- logger.error({ err }, 'Invalid newName passed to renameEntity')
- return callback(err)
}
- if (!SafePath.isCleanFilename(newName)) {
- return callback(new Errors.InvalidNameError('invalid element name'))
- }
- logger.debug({ entityId, projectId }, `renaming ${entityType}`)
- if (entityType == null) {
- logger.warn({ err: 'No entityType set', projectId, entityId })
- return callback(new Error('No entityType set'))
- }
- entityType = entityType.toLowerCase()
+ ),
- DocumentUpdaterHandler.flushProjectToMongo(projectId, err => {
- if (err) {
+ renameEntity: wrapWithLock(
+ function (
+ projectId,
+ entityId,
+ entityType,
+ newName,
+ userId,
+ source,
+ callback
+ ) {
+ if (!newName || typeof newName !== 'string') {
+ const err = new OError('invalid newName value', {
+ value: newName,
+ type: typeof newName,
+ projectId,
+ entityId,
+ entityType,
+ userId,
+ source,
+ })
+ logger.error({ err }, 'Invalid newName passed to renameEntity')
return callback(err)
}
- ProjectEntityMongoUpdateHandler.renameEntity(
- projectId,
- entityId,
- entityType,
- newName,
- (err, project, startPath, endPath, rev, changes) => {
- if (err != null) {
- return callback(err)
- }
- const projectHistoryId =
- project.overleaf &&
- project.overleaf.history &&
- project.overleaf.history.id
- TpdsUpdateSender.moveEntity(
- {
- projectId,
- projectName: project.name,
- startPath,
- endPath,
- rev,
- entityId,
- entityType,
- folderId: null, // this means the folder has not changed
- },
- err => {
- if (err) {
- logger.error({ err }, 'error sending tpds update')
- }
- DocumentUpdaterHandler.updateProjectStructure(
- projectId,
- projectHistoryId,
- userId,
- changes,
- source,
- callback
- )
- }
- )
+ if (!SafePath.isCleanFilename(newName)) {
+ return callback(new Errors.InvalidNameError('invalid element name'))
+ }
+ logger.debug({ entityId, projectId }, `renaming ${entityType}`)
+ if (entityType == null) {
+ logger.warn({ err: 'No entityType set', projectId, entityId })
+ return callback(new Error('No entityType set'))
+ }
+ entityType = entityType.toLowerCase()
+
+ DocumentUpdaterHandler.flushProjectToMongo(projectId, err => {
+ if (err) {
+ return callback(err)
}
- )
- })
- }),
+ ProjectEntityMongoUpdateHandler.renameEntity(
+ projectId,
+ entityId,
+ entityType,
+ newName,
+ (err, project, startPath, endPath, rev, changes) => {
+ if (err != null) {
+ return callback(err)
+ }
+ const projectHistoryId =
+ project.overleaf &&
+ project.overleaf.history &&
+ project.overleaf.history.id
+ TpdsUpdateSender.moveEntity(
+ {
+ projectId,
+ projectName: project.name,
+ startPath,
+ endPath,
+ rev,
+ entityId,
+ entityType,
+ folderId: null, // this means the folder has not changed
+ },
+ err => {
+ if (err) {
+ logger.error({ err }, 'error sending tpds update')
+ }
+ DocumentUpdaterHandler.updateProjectStructure(
+ projectId,
+ projectHistoryId,
+ userId,
+ changes,
+ source,
+ callback
+ )
+ }
+ )
+ }
+ )
+ })
+ }
+ ),
// This doesn't directly update project structure but we need to take the lock
// to prevent anything else being queued before the resync update
@@ -1471,8 +1471,8 @@ const ProjectEntityUpdateHandler = {
const originalName = entity.folder
? entity.folder.name
: entity.doc
- ? entity.doc.name
- : entity.file.name
+ ? entity.doc.name
+ : entity.file.name
let newPath = entity.path
let newName = originalName
@@ -1540,8 +1540,8 @@ const ProjectEntityUpdateHandler = {
const entityId = entity.folder
? entity.folder._id
: entity.doc
- ? entity.doc._id
- : entity.file._id
+ ? entity.doc._id
+ : entity.file._id
const entityType = entity.folder ? 'folder' : entity.doc ? 'doc' : 'file'
ProjectEntityMongoUpdateHandler.renameEntity(
projectId,
diff --git a/services/web/app/src/Features/ServerAdmin/AdminController.js b/services/web/app/src/Features/ServerAdmin/AdminController.js
index c0920dbb82..f3c5a01431 100644
--- a/services/web/app/src/Features/ServerAdmin/AdminController.js
+++ b/services/web/app/src/Features/ServerAdmin/AdminController.js
@@ -93,19 +93,18 @@ const AdminController = {
})()
}
- return SystemMessageManager.getMessagesFromDB(function (
- error,
- systemMessages
- ) {
- if (error != null) {
- return next(error)
+ return SystemMessageManager.getMessagesFromDB(
+ function (error, systemMessages) {
+ if (error != null) {
+ return next(error)
+ }
+ return res.render('admin/index', {
+ title: 'System Admin',
+ openSockets,
+ systemMessages,
+ })
}
- return res.render('admin/index', {
- title: 'System Admin',
- openSockets,
- systemMessages,
- })
- })
+ )
},
disconnectAllUsers: (req, res) => {
diff --git a/services/web/app/src/Features/Subscription/FeaturesUpdater.js b/services/web/app/src/Features/Subscription/FeaturesUpdater.js
index 4c74c19247..725b176885 100644
--- a/services/web/app/src/Features/Subscription/FeaturesUpdater.js
+++ b/services/web/app/src/Features/Subscription/FeaturesUpdater.js
@@ -114,16 +114,14 @@ async function computeFeatures(userId) {
}
async function _getIndividualFeatures(userId) {
- const sub = await SubscriptionLocator.promises.getUserIndividualSubscription(
- userId
- )
+ const sub =
+ await SubscriptionLocator.promises.getUserIndividualSubscription(userId)
return _subscriptionToFeatures(sub)
}
async function _getGroupFeatureSets(userId) {
- const subs = await SubscriptionLocator.promises.getGroupSubscriptionsMemberOf(
- userId
- )
+ const subs =
+ await SubscriptionLocator.promises.getGroupSubscriptionsMemberOf(userId)
return (subs || []).map(_subscriptionToFeatures)
}
diff --git a/services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js b/services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js
index 91d30bffaa..40fe5cc5ba 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js
+++ b/services/web/app/src/Features/Subscription/SubscriptionGroupHandler.js
@@ -28,9 +28,8 @@ async function isUserPartOfGroup(userId, subscriptionId) {
}
async function getTotalConfirmedUsersInGroup(subscriptionId) {
- const subscription = await SubscriptionLocator.promises.getSubscription(
- subscriptionId
- )
+ const subscription =
+ await SubscriptionLocator.promises.getSubscription(subscriptionId)
return subscription?.member_ids?.length
}
diff --git a/services/web/app/src/Features/Subscription/SubscriptionHandler.js b/services/web/app/src/Features/Subscription/SubscriptionHandler.js
index 2849f49500..4ccbfde9e4 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionHandler.js
+++ b/services/web/app/src/Features/Subscription/SubscriptionHandler.js
@@ -207,9 +207,8 @@ async function syncSubscription(recurlySubscription, requesterData) {
// This is used because Recurly doesn't always attempt collection of paast due
// invoices after Paypal billing info were updated.
async function attemptPaypalInvoiceCollection(recurlyAccountCode) {
- const billingInfo = await RecurlyWrapper.promises.getBillingInfo(
- recurlyAccountCode
- )
+ const billingInfo =
+ await RecurlyWrapper.promises.getBillingInfo(recurlyAccountCode)
if (!billingInfo.paypal_billing_agreement_id) {
// this is not a Paypal user
diff --git a/services/web/app/src/Features/Subscription/SubscriptionUpdater.js b/services/web/app/src/Features/Subscription/SubscriptionUpdater.js
index a9bf0e44b9..297fd0c4ee 100644
--- a/services/web/app/src/Features/Subscription/SubscriptionUpdater.js
+++ b/services/web/app/src/Features/Subscription/SubscriptionUpdater.js
@@ -47,9 +47,8 @@ async function syncSubscription(
adminUserId,
requesterData = {}
) {
- let subscription = await SubscriptionLocator.promises.getUsersSubscription(
- adminUserId
- )
+ let subscription =
+ await SubscriptionLocator.promises.getUsersSubscription(adminUserId)
if (subscription == null) {
subscription = await _createNewSubscription(adminUserId)
}
diff --git a/services/web/app/src/Features/Subscription/TeamInvitesController.js b/services/web/app/src/Features/Subscription/TeamInvitesController.js
index a3766ef9e4..4a8c5e379f 100644
--- a/services/web/app/src/Features/Subscription/TeamInvitesController.js
+++ b/services/web/app/src/Features/Subscription/TeamInvitesController.js
@@ -66,9 +66,8 @@ async function viewInvite(req, res, next) {
const { token } = req.params
const userId = SessionManager.getLoggedInUserId(req.session)
- const { invite, subscription } = await TeamInvitesHandler.promises.getInvite(
- token
- )
+ const { invite, subscription } =
+ await TeamInvitesHandler.promises.getInvite(token)
if (!invite) {
return ErrorController.notFound(req, res)
}
diff --git a/services/web/app/src/Features/Subscription/TeamInvitesHandler.js b/services/web/app/src/Features/Subscription/TeamInvitesHandler.js
index 4540581ce4..da93ff2b7f 100644
--- a/services/web/app/src/Features/Subscription/TeamInvitesHandler.js
+++ b/services/web/app/src/Features/Subscription/TeamInvitesHandler.js
@@ -124,9 +124,8 @@ async function revokeInvite(teamManagerId, subscription, email) {
// email is in Subscription.invited_emails when they join. We'll remove this
// after a short while.
async function createTeamInvitesForLegacyInvitedEmail(email) {
- const teams = await SubscriptionLocator.promises.getGroupsWithEmailInvite(
- email
- )
+ const teams =
+ await SubscriptionLocator.promises.getGroupsWithEmailInvite(email)
return Promise.all(
teams.map(team => createInvite(team.admin_id, team, email))
)
diff --git a/services/web/app/src/Features/ThirdPartyDataStore/UpdateMerger.js b/services/web/app/src/Features/ThirdPartyDataStore/UpdateMerger.js
index 07cd1755af..e073ccdd54 100644
--- a/services/web/app/src/Features/ThirdPartyDataStore/UpdateMerger.js
+++ b/services/web/app/src/Features/ThirdPartyDataStore/UpdateMerger.js
@@ -43,9 +43,8 @@ async function writeUpdateToDisk(projectId, updateStream) {
}
async function _findExistingFileType(projectId, path) {
- const { docs, files } = await ProjectEntityHandler.promises.getAllEntities(
- projectId
- )
+ const { docs, files } =
+ await ProjectEntityHandler.promises.getAllEntities(projectId)
if (_.some(docs, d => d.path === path)) {
return 'doc'
}
diff --git a/services/web/app/src/Features/Uploads/ProjectUploadManager.js b/services/web/app/src/Features/Uploads/ProjectUploadManager.js
index 98e1d38bb9..b96f5bd850 100644
--- a/services/web/app/src/Features/Uploads/ProjectUploadManager.js
+++ b/services/web/app/src/Features/Uploads/ProjectUploadManager.js
@@ -119,12 +119,10 @@ async function _initializeProjectWithZipContents(
project,
contentsPath
) {
- const topLevelDir = await ArchiveManager.promises.findTopLevelDirectory(
- contentsPath
- )
- const importEntries = await FileSystemImportManager.promises.importDir(
- topLevelDir
- )
+ const topLevelDir =
+ await ArchiveManager.promises.findTopLevelDirectory(contentsPath)
+ const importEntries =
+ await FileSystemImportManager.promises.importDir(topLevelDir)
const { fileEntries, docEntries } = await _createEntriesFromImports(
project._id,
importEntries
diff --git a/services/web/app/src/Features/User/SAMLIdentityManager.js b/services/web/app/src/Features/User/SAMLIdentityManager.js
index 5bfb4a8ddd..ab71950087 100644
--- a/services/web/app/src/Features/User/SAMLIdentityManager.js
+++ b/services/web/app/src/Features/User/SAMLIdentityManager.js
@@ -32,9 +32,8 @@ async function _ensureCanAddIdentifier(userId, institutionEmail, providerId) {
throw new Errors.SAMLAlreadyLinkedError()
}
- const userWithEmail = await UserGetter.promises.getUserByAnyEmail(
- institutionEmail
- )
+ const userWithEmail =
+ await UserGetter.promises.getUserByAnyEmail(institutionEmail)
if (!userWithEmail) {
// email doesn't exist; all good
diff --git a/services/web/app/src/Features/User/UserDeleter.js b/services/web/app/src/Features/User/UserDeleter.js
index 27019ab3b5..49d0f0b264 100644
--- a/services/web/app/src/Features/User/UserDeleter.js
+++ b/services/web/app/src/Features/User/UserDeleter.js
@@ -103,9 +103,8 @@ async function expireDeletedUsersAfterDuration() {
}
async function ensureCanDeleteUser(user) {
- const subscription = await SubscriptionLocator.promises.getUsersSubscription(
- user
- )
+ const subscription =
+ await SubscriptionLocator.promises.getUsersSubscription(user)
if (subscription) {
throw new Errors.SubscriptionAdminDeletionError({})
}
diff --git a/services/web/app/src/Features/User/UserGetter.js b/services/web/app/src/Features/User/UserGetter.js
index 447c9b1c4f..2d68f3c24d 100644
--- a/services/web/app/src/Features/User/UserGetter.js
+++ b/services/web/app/src/Features/User/UserGetter.js
@@ -68,9 +68,8 @@ async function getUserFullEmails(userId) {
return decorateFullEmails(user.email, user.emails, [], [])
}
- const affiliationsData = await InstitutionsAPIPromises.getUserAffiliations(
- userId
- )
+ const affiliationsData =
+ await InstitutionsAPIPromises.getUserAffiliations(userId)
return decorateFullEmails(
user.email,
diff --git a/services/web/app/src/Features/User/UserPostRegistrationAnalyticsManager.js b/services/web/app/src/Features/User/UserPostRegistrationAnalyticsManager.js
index deb51c28e2..26dbf86e26 100644
--- a/services/web/app/src/Features/User/UserPostRegistrationAnalyticsManager.js
+++ b/services/web/app/src/Features/User/UserPostRegistrationAnalyticsManager.js
@@ -24,9 +24,8 @@ async function postRegistrationAnalytics(userId) {
}
async function checkAffiliations(userId) {
- const affiliationsData = await InstitutionsAPIPromises.getUserAffiliations(
- userId
- )
+ const affiliationsData =
+ await InstitutionsAPIPromises.getUserAffiliations(userId)
const hasCommonsAccountAffiliation = affiliationsData.some(
affiliationData =>
affiliationData.institution && affiliationData.institution.commonsAccount
diff --git a/services/web/app/src/Features/User/UserUpdater.js b/services/web/app/src/Features/User/UserUpdater.js
index 1bd4e056f7..e9613f6811 100644
--- a/services/web/app/src/Features/User/UserUpdater.js
+++ b/services/web/app/src/Features/User/UserUpdater.js
@@ -354,9 +354,8 @@ async function maybeCreateRedundantSubscriptionNotification(userId, email) {
return
}
- const affiliations = await InstitutionsAPI.promises.getUserAffiliations(
- userId
- )
+ const affiliations =
+ await InstitutionsAPI.promises.getUserAffiliations(userId)
const confirmedAffiliation = affiliations.find(a => a.email === email)
if (!confirmedAffiliation || confirmedAffiliation.licence === 'free') {
return
diff --git a/services/web/app/src/infrastructure/Modules.js b/services/web/app/src/infrastructure/Modules.js
index 112d051ee8..cabfbefb10 100644
--- a/services/web/app/src/infrastructure/Modules.js
+++ b/services/web/app/src/infrastructure/Modules.js
@@ -30,11 +30,9 @@ function loadModules() {
}
for (const moduleName of Settings.moduleImportSequence || []) {
- const loadedModule = require(Path.join(
- MODULE_BASE_PATH,
- moduleName,
- 'index.js'
- ))
+ const loadedModule = require(
+ Path.join(MODULE_BASE_PATH, moduleName, 'index.js')
+ )
loadedModule.name = moduleName
_modules.push(loadedModule)
}
diff --git a/services/web/frontend/fonts/font-awesome.css b/services/web/frontend/fonts/font-awesome.css
index 5cbae8e590..0c31964a4c 100644
--- a/services/web/frontend/fonts/font-awesome.css
+++ b/services/web/frontend/fonts/font-awesome.css
@@ -4,7 +4,8 @@
*/
@font-face {
font-family: 'FontAwesome';
- src: url('font-awesome-v470.woff2') format('woff2'),
+ src:
+ url('font-awesome-v470.woff2') format('woff2'),
url('font-awesome-v470.woff') format('woff');
font-weight: normal;
font-style: normal;
diff --git a/services/web/frontend/fonts/lato.css b/services/web/frontend/fonts/lato.css
index 2d616c9206..16d2dd953b 100644
--- a/services/web/frontend/fonts/lato.css
+++ b/services/web/frontend/fonts/lato.css
@@ -2,7 +2,8 @@
font-family: 'Lato';
font-style: normal;
font-weight: 400;
- src: url('lato/lato-v2-latin-ext-regular.woff2') format('woff2'),
+ src:
+ url('lato/lato-v2-latin-ext-regular.woff2') format('woff2'),
url('lato/lato-v2-latin-ext-regular.woff') format('woff');
}
@@ -10,7 +11,8 @@
font-family: 'Lato';
font-style: italic;
font-weight: 400;
- src: url('lato/lato-v2-latin-ext-italic.woff2') format('woff2'),
+ src:
+ url('lato/lato-v2-latin-ext-italic.woff2') format('woff2'),
url('lato/lato-v2-latin-ext-italic.woff') format('woff');
}
@@ -18,7 +20,8 @@
font-family: 'Lato';
font-style: normal;
font-weight: 700;
- src: url('lato/lato-v2-latin-ext-700.woff2') format('woff2'),
+ src:
+ url('lato/lato-v2-latin-ext-700.woff2') format('woff2'),
url('lato/lato-v2-latin-ext-700.woff') format('woff');
}
@@ -26,6 +29,7 @@
font-family: 'Lato';
font-style: italic;
font-weight: 700;
- src: url('lato/lato-v2-latin-ext-700italic.woff2') format('woff2'),
+ src:
+ url('lato/lato-v2-latin-ext-700italic.woff2') format('woff2'),
url('lato/lato-v2-latin-ext-700italic.woff') format('woff');
}
diff --git a/services/web/frontend/fonts/material-symbols.css b/services/web/frontend/fonts/material-symbols.css
index 5244dc73ed..df48c82f46 100644
--- a/services/web/frontend/fonts/material-symbols.css
+++ b/services/web/frontend/fonts/material-symbols.css
@@ -15,7 +15,11 @@
font-weight: normal;
font-style: normal;
font-size: 20px;
- font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 20;
+ font-variation-settings:
+ 'FILL' 1,
+ 'wght' 400,
+ 'GRAD' 0,
+ 'opsz' 20;
line-height: 1;
letter-spacing: normal;
text-transform: none;
diff --git a/services/web/frontend/fonts/merriweather.css b/services/web/frontend/fonts/merriweather.css
index 61787faee8..aa53e02420 100644
--- a/services/web/frontend/fonts/merriweather.css
+++ b/services/web/frontend/fonts/merriweather.css
@@ -2,7 +2,9 @@
font-family: 'Merriweather';
font-style: normal;
font-weight: 400;
- src: local('Merriweather Regular'), local('Merriweather-Regular'),
+ src:
+ local('Merriweather Regular'),
+ local('Merriweather-Regular'),
url('merriweather-v21-latin-regular.woff2') format('woff2'),
url('merriweather-v21-latin-regular.woff') format('woff');
}
@@ -10,7 +12,9 @@
font-family: 'Merriweather';
font-style: italic;
font-weight: 400;
- src: local('Merriweather Italic'), local('Merriweather-Italic'),
+ src:
+ local('Merriweather Italic'),
+ local('Merriweather-Italic'),
url('merriweather-v21-latin-italic.woff2') format('woff2'),
url('merriweather-v21-latin-italic.woff') format('woff');
}
@@ -18,7 +22,9 @@
font-family: 'Merriweather';
font-style: normal;
font-weight: 700;
- src: local('Merriweather Bold'), local('Merriweather-Bold'),
+ src:
+ local('Merriweather Bold'),
+ local('Merriweather-Bold'),
url('merriweather-v21-latin-700.woff2') format('woff2'),
url('merriweather-v21-latin-700.woff') format('woff');
}
@@ -26,7 +32,9 @@
font-family: 'Merriweather';
font-style: italic;
font-weight: 700;
- src: local('Merriweather Bold Italic'), local('Merriweather-BoldItalic'),
+ src:
+ local('Merriweather Bold Italic'),
+ local('Merriweather-BoldItalic'),
url('merriweather-v21-latin-700italic.woff2') format('woff2'),
url('merriweather-v21-latin-700italic.woff') format('woff');
}
diff --git a/services/web/frontend/fonts/open-sans.css b/services/web/frontend/fonts/open-sans.css
index ae38b38bb8..236dbf63d8 100644
--- a/services/web/frontend/fonts/open-sans.css
+++ b/services/web/frontend/fonts/open-sans.css
@@ -2,7 +2,9 @@
font-family: 'Open Sans';
font-style: normal;
font-weight: 300;
- src: local('Open Sans Light'), local('OpenSans-Light'),
+ src:
+ local('Open Sans Light'),
+ local('OpenSans-Light'),
url('open-sans-v17-latin-300.woff2') format('woff2'),
url('open-sans-v17-latin-300.woff') format('woff');
}
@@ -10,7 +12,9 @@
font-family: 'Open Sans';
font-style: normal;
font-weight: 400;
- src: local('Open Sans Regular'), local('OpenSans-Regular'),
+ src:
+ local('Open Sans Regular'),
+ local('OpenSans-Regular'),
url('open-sans-v17-latin-regular.woff2') format('woff2'),
url('open-sans-v17-latin-regular.woff') format('woff');
}
@@ -18,7 +22,9 @@
font-family: 'Open Sans';
font-style: normal;
font-weight: 600;
- src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'),
+ src:
+ local('Open Sans SemiBold'),
+ local('OpenSans-SemiBold'),
url('open-sans-v17-latin-600.woff2') format('woff2'),
url('open-sans-v17-latin-600.woff') format('woff');
}
@@ -26,7 +32,9 @@
font-family: 'Open Sans';
font-style: normal;
font-weight: 700;
- src: local('Open Sans Bold'), local('OpenSans-Bold'),
+ src:
+ local('Open Sans Bold'),
+ local('OpenSans-Bold'),
url('open-sans-v17-latin-700.woff2') format('woff2'),
url('open-sans-v17-latin-700.woff') format('woff');
}
diff --git a/services/web/frontend/fonts/source-code-pro.css b/services/web/frontend/fonts/source-code-pro.css
index be0d2ff03b..f52eb466af 100644
--- a/services/web/frontend/fonts/source-code-pro.css
+++ b/services/web/frontend/fonts/source-code-pro.css
@@ -2,7 +2,9 @@
font-family: 'Source Code Pro';
font-style: normal;
font-weight: 400;
- src: local('Source Code Pro Regular'), local('SourceCodePro-Regular'),
+ src:
+ local('Source Code Pro Regular'),
+ local('SourceCodePro-Regular'),
url('source-code-pro-v13-latin-regular.woff2') format('woff2'),
url('source-code-pro-v13-latin-regular.woff') format('woff');
}
diff --git a/services/web/frontend/js/features/history/utils/auto-select-file.ts b/services/web/frontend/js/features/history/utils/auto-select-file.ts
index 5d309e8866..add1c5a27d 100644
--- a/services/web/frontend/js/features/history/utils/auto-select-file.ts
+++ b/services/web/frontend/js/features/history/utils/auto-select-file.ts
@@ -75,16 +75,19 @@ function getFilesWithOps(
return filesWithOps
} else {
- const filesWithOps = files.reduce((curFilesWithOps, file) => {
- if ('operation' in file) {
- curFilesWithOps.push({
- pathname: file.pathname,
- editable: isFileEditable(file),
- operation: file.operation,
- })
- }
- return curFilesWithOps
- }, [])
+ const filesWithOps = files.reduce(
+ (curFilesWithOps, file) => {
+ if ('operation' in file) {
+ curFilesWithOps.push({
+ pathname: file.pathname,
+ editable: isFileEditable(file),
+ operation: file.operation,
+ })
+ }
+ return curFilesWithOps
+ },
+ []
+ )
return filesWithOps
}
diff --git a/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts b/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts
index 82059ad3db..ef990876fc 100644
--- a/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts
+++ b/services/web/frontend/js/features/ide-react/context/review-panel/hooks/use-review-panel-state.ts
@@ -226,8 +226,8 @@ function useReviewPanelState(): ReviewPanel.ReviewPanelState {
MergeAndOverride<
ReviewPanelCommentThread,
ReviewPanelCommentThreadsApi[ThreadId]
- >
- ]
+ >,
+ ],
]
for (const [threadId, thread] of threadsEntries) {
for (const comment of thread.messages) {
@@ -565,8 +565,8 @@ function useReviewPanelState(): ReviewPanel.ReviewPanelState {
[
UserId,
NonNullable<
- typeof trackChangesState[keyof typeof trackChangesState]
- >
+ (typeof trackChangesState)[keyof typeof trackChangesState]
+ >,
]
>
for (const [userId, { value }] of entries) {
@@ -605,7 +605,7 @@ function useReviewPanelState(): ReviewPanel.ReviewPanelState {
}
const state =
newTrackChangesState[userId] ??
- ({} as NonNullable)
+ ({} as NonNullable<(typeof newTrackChangesState)[UserId]>)
newTrackChangesState[userId] = state
if (state.syncState == null || state.syncState === 'synced') {
diff --git a/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts b/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts
index 9d17905215..521596bcd4 100644
--- a/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts
+++ b/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts
@@ -69,8 +69,8 @@ export function useEditingSessionHeartbeat() {
heartbeatsSent <= 2
? 30
: heartbeatsSent <= 6
- ? (heartbeatsSent - 2) * 60
- : 300
+ ? (heartbeatsSent - 2) * 60
+ : 300
setNextHeartbeatAt(moment().add(backoffSecs, 'seconds').toDate())
}, [getEditorType, heartbeatsSent, nextHeartbeatAt, projectId])
diff --git a/services/web/frontend/js/features/pdf-preview/components/faster-compiles-feedback.tsx b/services/web/frontend/js/features/pdf-preview/components/faster-compiles-feedback.tsx
index 48b05337b4..da89efc4d4 100644
--- a/services/web/frontend/js/features/pdf-preview/components/faster-compiles-feedback.tsx
+++ b/services/web/frontend/js/features/pdf-preview/components/faster-compiles-feedback.tsx
@@ -111,8 +111,8 @@ function FasterCompilesFeedbackContent() {
{feedback === 'faster'
? t('faster_compiles_feedback_seems_faster')
: feedback === 'same'
- ? t('faster_compiles_feedback_seems_same')
- : t('faster_compiles_feedback_seems_slower')}
+ ? t('faster_compiles_feedback_seems_same')
+ : t('faster_compiles_feedback_seems_slower')}
))}
diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.jsx b/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.jsx
index 500ae2ff72..c4d79243b4 100644
--- a/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.jsx
+++ b/services/web/frontend/js/features/pdf-preview/components/pdf-viewer.jsx
@@ -1,8 +1,8 @@
import { lazy, memo } from 'react'
import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
-const PdfJsViewer = lazy(() =>
- import(/* webpackChunkName: "pdf-js-viewer" */ './pdf-js-viewer')
+const PdfJsViewer = lazy(
+ () => import(/* webpackChunkName: "pdf-js-viewer" */ './pdf-js-viewer')
)
function PdfViewer() {
diff --git a/services/web/frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner.tsx b/services/web/frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner.tsx
index f728fc7bfc..6be16fccb2 100644
--- a/services/web/frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner.tsx
+++ b/services/web/frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner.tsx
@@ -7,7 +7,7 @@ import { useProjectListContext } from '../../context/project-list-context'
import { useTranslation } from 'react-i18next'
const variants = ['did-you-know', 'on-premise', 'people', 'FOMO'] as const
-type GroupsAndEnterpriseBannerVariant = typeof variants[number]
+type GroupsAndEnterpriseBannerVariant = (typeof variants)[number]
let viewEventSent = false
diff --git a/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/tags-dropdown.tsx b/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/tags-dropdown.tsx
index b597e4746d..c129c1582f 100644
--- a/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/tags-dropdown.tsx
+++ b/services/web/frontend/js/features/project-list/components/table/project-tools/buttons/tags-dropdown.tsx
@@ -116,8 +116,8 @@ function TagsDropdown() {
containsAllSelectedProjects(tag)
? 'check-square-o'
: containsSomeSelectedProjects(tag)
- ? 'minus-square-o'
- : 'square-o'
+ ? 'minus-square-o'
+ : 'square-o'
}
className="tag-checkbox"
/>{' '}
diff --git a/services/web/frontend/js/features/settings/components/emails/add-email/country-input.tsx b/services/web/frontend/js/features/settings/components/emails/add-email/country-input.tsx
index b676f56ddf..f90fdb6152 100644
--- a/services/web/frontend/js/features/settings/components/emails/add-email/country-input.tsx
+++ b/services/web/frontend/js/features/settings/components/emails/add-email/country-input.tsx
@@ -9,7 +9,8 @@ type CountryInputProps = {
inputRef?: React.ForwardedRef
} & React.InputHTMLAttributes
-const itemToString = (item: typeof countries[number] | null) => item?.name ?? ''
+const itemToString = (item: (typeof countries)[number] | null) =>
+ item?.name ?? ''
function Downshift({ setValue, inputRef }: CountryInputProps) {
const { t } = useTranslation()
diff --git a/services/web/frontend/js/features/settings/domain-blocklist.ts b/services/web/frontend/js/features/settings/domain-blocklist.ts
index 32b4bcb6de..4e31a5cfd0 100644
--- a/services/web/frontend/js/features/settings/domain-blocklist.ts
+++ b/services/web/frontend/js/features/settings/domain-blocklist.ts
@@ -58,4 +58,6 @@ for (const domain of commonDomains) {
}
}
-export default domainBlocklist as ReadonlyArray
+export default domainBlocklist as ReadonlyArray<
+ (typeof domainBlocklist)[number]
+>
diff --git a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx
index 929c73f543..d77cdf3db9 100644
--- a/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx
+++ b/services/web/frontend/js/features/source-editor/components/figure-modal/figure-modal.tsx
@@ -268,8 +268,8 @@ const FigureModalContent = () => {
{helpShown
? t('help')
: sourcePickerShown
- ? t('replace_figure')
- : getTitle(source)}{' '}
+ ? t('replace_figure')
+ : getTitle(source)}{' '}
{
uploading
? FileUploadStatus.UPLOADING
: uploadError
- ? FileUploadStatus.ERROR
- : FileUploadStatus.NOT_ATTEMPTED
+ ? FileUploadStatus.ERROR
+ : FileUploadStatus.NOT_ATTEMPTED
}
onDelete={() => {
uppy.removeFile(file.id)
diff --git a/services/web/frontend/js/features/source-editor/components/review-panel/utils/compare-props-with-shallow-array-compare.ts b/services/web/frontend/js/features/source-editor/components/review-panel/utils/compare-props-with-shallow-array-compare.ts
index 07ad6def04..c50a5edd73 100644
--- a/services/web/frontend/js/features/source-editor/components/review-panel/utils/compare-props-with-shallow-array-compare.ts
+++ b/services/web/frontend/js/features/source-editor/components/review-panel/utils/compare-props-with-shallow-array-compare.ts
@@ -4,7 +4,7 @@ const shallowEqual = (arr1: unknown[], arr2: unknown[]) =>
// Compares props for a component, but comparing the specified props using
// shallow array comparison rather than identity
export default function comparePropsWithShallowArrayCompare<
- T extends Record
+ T extends Record,
>(...args: Array) {
return (prevProps: T, nextProps: T) => {
for (const k in prevProps) {
diff --git a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts
index b715fc02fe..0d8798f275 100644
--- a/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts
+++ b/services/web/frontend/js/features/source-editor/components/table-generator/toolbar/commands.ts
@@ -747,9 +747,8 @@ export const setColumnWidth = (
const alignmentCharacter = getParagraphAlignmentCharacter(
columnSpecification[i]
)
- columnSpecification[
- i
- ].content = `${alignmentCharacter}{${widthValue}${suffix}}`
+ columnSpecification[i].content =
+ `${alignmentCharacter}{${widthValue}${suffix}}`
}
}
const newSpecification = generateColumnSpecification(columnSpecification)
diff --git a/services/web/frontend/js/features/source-editor/extensions/browser.ts b/services/web/frontend/js/features/source-editor/extensions/browser.ts
index 52da810b49..465846f1c7 100644
--- a/services/web/frontend/js/features/source-editor/extensions/browser.ts
+++ b/services/web/frontend/js/features/source-editor/extensions/browser.ts
@@ -28,10 +28,10 @@ export default {
ie_version: ieUpTo10
? doc.documentMode || 6
: ie11Up
- ? +ie11Up[1]
- : ieEdge
- ? +ieEdge[1]
- : 0,
+ ? +ie11Up[1]
+ : ieEdge
+ ? +ieEdge[1]
+ : 0,
gecko,
gecko_version: gecko
? +(/Firefox\/(\d+)/.exec(nav.userAgent) || [0, 0])[1]
diff --git a/services/web/frontend/js/features/source-editor/extensions/track-changes.ts b/services/web/frontend/js/features/source-editor/extensions/track-changes.ts
index cee664ecc0..461b8f78ca 100644
--- a/services/web/frontend/js/features/source-editor/extensions/track-changes.ts
+++ b/services/web/frontend/js/features/source-editor/extensions/track-changes.ts
@@ -221,7 +221,10 @@ class ChangeDeletedWidget extends WidgetType {
}
class ChangeCalloutWidget extends WidgetType {
- constructor(public change: Change, public opType: string) {
+ constructor(
+ public change: Change,
+ public opType: string
+ ) {
super()
}
diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
index 7e9f2966c0..d4d75cdcf8 100644
--- a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
+++ b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts
@@ -542,7 +542,7 @@ const createSelector = <
T extends string,
E extends HTMLElement = T extends keyof HTMLElementTagNameMap
? HTMLElementTagNameMap[T]
- : HTMLElement
+ : HTMLElement,
>({
selector,
...elementSelector
diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/pasted-content.tsx b/services/web/frontend/js/features/source-editor/extensions/visual/pasted-content.tsx
index e6628ae699..061c77d315 100644
--- a/services/web/frontend/js/features/source-editor/extensions/visual/pasted-content.tsx
+++ b/services/web/frontend/js/features/source-editor/extensions/visual/pasted-content.tsx
@@ -13,8 +13,10 @@ import { SplitTestProvider } from '../../../../shared/context/split-test-context
export type PastedContent = { latex: string; text: string }
-const pastedContentEffect =
- StateEffect.define<{ content: PastedContent; formatted: boolean }>()
+const pastedContentEffect = StateEffect.define<{
+ content: PastedContent
+ formatted: boolean
+}>()
export const insertPastedContent = (
view: EditorView,
diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/environment-line.ts b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/environment-line.ts
index 1d3ef080f6..47d30812e9 100644
--- a/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/environment-line.ts
+++ b/services/web/frontend/js/features/source-editor/extensions/visual/visual-widgets/environment-line.ts
@@ -1,7 +1,10 @@
import { EditorView, WidgetType } from '@codemirror/view'
export class EnvironmentLineWidget extends WidgetType {
- constructor(public environment: string, public line?: 'begin' | 'end') {
+ constructor(
+ public environment: string,
+ public line?: 'begin' | 'end'
+ ) {
super()
}
diff --git a/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js b/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js
index 2c9c8f8cd5..ba622f71e2 100644
--- a/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js
+++ b/services/web/frontend/js/ide/review-panel/controllers/ReviewPanelController.js
@@ -371,9 +371,8 @@ export default App.controller('ReviewPanelController', [
ide.$scope.reviewPanel.overview.docsCollapsedState[doc.id] ==
null
) {
- ide.$scope.reviewPanel.overview.docsCollapsedState[
- doc.id
- ] = false
+ ide.$scope.reviewPanel.overview.docsCollapsedState[doc.id] =
+ false
}
if (doc.id !== $scope.editor.open_doc_id) {
// this is kept up to date in real-time, don't overwrite
diff --git a/services/web/frontend/js/main/event.js b/services/web/frontend/js/main/event.js
index d85999b175..b3e64cf7c3 100644
--- a/services/web/frontend/js/main/event.js
+++ b/services/web/frontend/js/main/event.js
@@ -93,8 +93,8 @@ App.factory('eventTracking', [
heartbeatsSent <= 2
? 30
: heartbeatsSent <= 6
- ? (heartbeatsSent - 2) * 60
- : 300
+ ? (heartbeatsSent - 2) * 60
+ : 300
nextHeartbeat = moment().add(backoffSecs, 'seconds').toDate()
},
diff --git a/services/web/frontend/js/shared/context/project-context.tsx b/services/web/frontend/js/shared/context/project-context.tsx
index 36f79b45b4..f016bc54b4 100644
--- a/services/web/frontend/js/shared/context/project-context.tsx
+++ b/services/web/frontend/js/shared/context/project-context.tsx
@@ -94,8 +94,8 @@ export const ProjectProvider: FC = ({ children }) => {
forceNewCompileTimeout === 'active'
? 'active'
: forceNewCompileTimeout === 'changing'
- ? 'changing'
- : undefined
+ ? 'changing'
+ : undefined
const value = useMemo(() => {
return {
diff --git a/services/web/frontend/js/utils/functions.ts b/services/web/frontend/js/utils/functions.ts
index 3cdbf0d6c6..dfc46d8cad 100644
--- a/services/web/frontend/js/utils/functions.ts
+++ b/services/web/frontend/js/utils/functions.ts
@@ -1,6 +1,6 @@
export function callFnsInSequence<
Args,
- Fn extends ((...args: Args[]) => void) | void
+ Fn extends ((...args: Args[]) => void) | void,
>(...fns: Fn[]) {
return (...args: Args[]) => fns.forEach(fn => fn?.(...args))
}
diff --git a/services/web/frontend/stylesheets/app/editor/logs.less b/services/web/frontend/stylesheets/app/editor/logs.less
index 5074321770..32573a2d56 100644
--- a/services/web/frontend/stylesheets/app/editor/logs.less
+++ b/services/web/frontend/stylesheets/app/editor/logs.less
@@ -155,7 +155,9 @@
position: relative;
height: 40px;
margin-top: 0;
- transition: margin 0.15s ease-in-out, opacity 0.15s ease-in-out;
+ transition:
+ margin 0.15s ease-in-out,
+ opacity 0.15s ease-in-out;
padding-bottom: @padding-sm;
text-align: center;
background-image: linear-gradient(0, @ol-blue-gray-1, transparent);
diff --git a/services/web/frontend/stylesheets/app/editor/pdf.less b/services/web/frontend/stylesheets/app/editor/pdf.less
index 7a1ba0bb84..880a7a7027 100644
--- a/services/web/frontend/stylesheets/app/editor/pdf.less
+++ b/services/web/frontend/stylesheets/app/editor/pdf.less
@@ -47,7 +47,11 @@
}
.toolbar-pdf-hybrid {
- .btn:not(.detach-compile-button):not(.btn-orphan):not(.detach-synctex-control):not(.switch-to-editor-btn):not(.split-menu-dropdown-toggle):not(.split-menu-button) {
+ .btn:not(.detach-compile-button):not(.btn-orphan):not(
+ .detach-synctex-control
+ ):not(.switch-to-editor-btn):not(.split-menu-dropdown-toggle):not(
+ .split-menu-button
+ ) {
display: inline-block;
color: @toolbar-btn-color;
background-color: transparent;
@@ -208,7 +212,9 @@
z-index: 10; // above the PDF viewer
.btn-group {
- transition: opacity 0.5s ease, visibility 0 linear 0.5s;
+ transition:
+ opacity 0.5s ease,
+ visibility 0 linear 0.5s;
visibility: hidden;
opacity: 0;
}
diff --git a/services/web/frontend/stylesheets/app/editor/review-panel.less b/services/web/frontend/stylesheets/app/editor/review-panel.less
index 80d7e2b394..ad7afe8a69 100644
--- a/services/web/frontend/stylesheets/app/editor/review-panel.less
+++ b/services/web/frontend/stylesheets/app/editor/review-panel.less
@@ -231,10 +231,15 @@
border-radius: 3px;
color: #fff;
cursor: pointer;
- transition: top @rp-entry-animation-speed, left 0.1s, right 0.1s;
+ transition:
+ top @rp-entry-animation-speed,
+ left 0.1s,
+ right 0.1s;
.no-animate & {
- transition: left 0.1s, right 0.1s;
+ transition:
+ left 0.1s,
+ right 0.1s;
}
&-focused {
@@ -381,10 +386,15 @@
border-left: solid @rp-entry-ribbon-width transparent;
border-radius: 3px;
background-color: #fff;
- transition: top @rp-entry-animation-speed, left 0.1s, right 0.1s;
+ transition:
+ top @rp-entry-animation-speed,
+ left 0.1s,
+ right 0.1s;
.no-animate & {
- transition: left 0.1s, right 0.1s;
+ transition:
+ left 0.1s,
+ right 0.1s;
}
&-insert,
@@ -407,8 +417,11 @@
z-index: 3;
transform: scale(0.1);
transform-origin: 0 0;
- transition: top 0.35s ease-out, left 0.35s ease-out,
- transform 0.35s ease-out, opacity 0.35s ease-out 0.2s;
+ transition:
+ top 0.35s ease-out,
+ left 0.35s ease-out,
+ transform 0.35s ease-out,
+ opacity 0.35s ease-out 0.2s;
}
&-comment-resolved {
@@ -654,7 +667,9 @@
}
.rp-entry-callout {
- transition: top @rp-entry-animation-speed, height @rp-entry-animation-speed;
+ transition:
+ top @rp-entry-animation-speed,
+ height @rp-entry-animation-speed;
.rp-state-current-file & {
position: absolute;
diff --git a/services/web/frontend/stylesheets/app/editor/toolbar.less b/services/web/frontend/stylesheets/app/editor/toolbar.less
index 31d535d3d1..a27532b7ef 100644
--- a/services/web/frontend/stylesheets/app/editor/toolbar.less
+++ b/services/web/frontend/stylesheets/app/editor/toolbar.less
@@ -252,7 +252,9 @@
user-select: none;
color: @text-color;
border-radius: @btn-border-radius-base;
- transition: color 0.12s ease-out, background-color 0.12s ease-out,
+ transition:
+ color 0.12s ease-out,
+ background-color 0.12s ease-out,
box-shadow 0.12s ease-out;
overflow: hidden;
diff --git a/services/web/frontend/stylesheets/app/plans/plans-v2.less b/services/web/frontend/stylesheets/app/plans/plans-v2.less
index 8251446779..6d2f3f969a 100644
--- a/services/web/frontend/stylesheets/app/plans/plans-v2.less
+++ b/services/web/frontend/stylesheets/app/plans/plans-v2.less
@@ -590,7 +590,9 @@ span.plans-v2-license-picker-educational-discount-learn-more-container {
background-clip: padding-box; /* needed for firefox when there is bg color */
text-align: center;
- &:not(.plans-v2-table-cell-before-green-highlighted-column):not(.plans-v2-table-green-highlighted):not(.plans-v2-table-divider-highlighted) {
+ &:not(.plans-v2-table-cell-before-green-highlighted-column):not(
+ .plans-v2-table-green-highlighted
+ ):not(.plans-v2-table-divider-highlighted) {
border-right: 1px solid @ol-blue-gray-0;
@media (max-width: @screen-xs-max) {
@@ -623,7 +625,9 @@ span.plans-v2-license-picker-educational-discount-learn-more-container {
vertical-align: middle;
height: 100%;
- &:last-child:not(.plans-v2-table-green-highlighted):not(.plans-v2-table-divider-highlighted) {
+ &:last-child:not(.plans-v2-table-green-highlighted):not(
+ .plans-v2-table-divider-highlighted
+ ) {
border-right: 0;
}
}
@@ -649,7 +653,9 @@ span.plans-v2-license-picker-educational-discount-learn-more-container {
}
}
- &:not(.plans-v2-table-row-last-row-per-section):not(.plans-v2-table-divider):not(:last-of-type) {
+ &:not(.plans-v2-table-row-last-row-per-section):not(
+ .plans-v2-table-divider
+ ):not(:last-of-type) {
th > .plans-v2-table-th > .plans-v2-table-th-content,
td > .plans-v2-table-feature-name,
td > .plans-v2-table-cell > .plans-v2-table-cell-content {
diff --git a/services/web/frontend/stylesheets/app/project-list-react.less b/services/web/frontend/stylesheets/app/project-list-react.less
index 4174eebade..76bc4bfbf4 100644
--- a/services/web/frontend/stylesheets/app/project-list-react.less
+++ b/services/web/frontend/stylesheets/app/project-list-react.less
@@ -923,7 +923,10 @@
vertical-align: middle;
&:focus-visible {
- box-shadow: 0 0 0 2px @white, 0 0 0 3px @blue-50, 0 0 0 5px @blue-30;
+ box-shadow:
+ 0 0 0 2px @white,
+ 0 0 0 3px @blue-50,
+ 0 0 0 5px @blue-30;
}
&.more-button {
diff --git a/services/web/frontend/stylesheets/app/review-features-page.less b/services/web/frontend/stylesheets/app/review-features-page.less
index 6144e67abf..35e62f2d7c 100644
--- a/services/web/frontend/stylesheets/app/review-features-page.less
+++ b/services/web/frontend/stylesheets/app/review-features-page.less
@@ -214,7 +214,9 @@
display: inline-block;
transform: translate(150px, 0);
opacity: 0;
- transition: transform 0.8s ease 0s, opacity 0.8s ease 0s;
+ transition:
+ transform 0.8s ease 0s,
+ opacity 0.8s ease 0s;
&:nth-child(2) {
transition-delay: 0.5s, 0.5s;
}
@@ -244,7 +246,9 @@
margin-bottom: 2em;
transform: translate(0, 100px);
opacity: 0;
- transition: transform 0.8s ease 1s, opacity 0.8s ease 1s;
+ transition:
+ transform 0.8s ease 1s,
+ opacity 0.8s ease 1s;
box-shadow: none;
max-width: none;
@@ -271,7 +275,9 @@
}
}
.rfp-video-anim {
- transition: transform 0.8s ease, opacity 0.8s ease;
+ transition:
+ transform 0.8s ease,
+ opacity 0.8s ease;
transform: translate(100%, 0);
opacity: 0;
}
@@ -294,7 +300,7 @@
border-left: 0;
max-width: 30em;
font-size: @rfp-lead-size;
- quotes: '\201C''\201D';
+ quotes: '\201C' '\201D';
box-shadow: @rfp-card-shadow;
border-radius: @rfp-border-radius;
background-color: #fff;
@@ -333,7 +339,7 @@
border-left: 0;
margin: 0 auto;
padding: 0;
- quotes: '\201C''\201D';
+ quotes: '\201C' '\201D';
font-size: @rfp-lead-size;
@media (min-width: @screen-md-min) {
display: flex;
@@ -454,7 +460,9 @@
position: absolute;
left: 50%;
text-transform: uppercase;
- transition: opacity 0.25s, transform 0.25s;
+ transition:
+ opacity 0.25s,
+ transform 0.25s;
transform: translate(-50%, 100%);
opacity: 0;
font-size: 0.5em;
diff --git a/services/web/frontend/stylesheets/app/website-redesign.less b/services/web/frontend/stylesheets/app/website-redesign.less
index 2fdd4ad1f5..bcefe47e20 100644
--- a/services/web/frontend/stylesheets/app/website-redesign.less
+++ b/services/web/frontend/stylesheets/app/website-redesign.less
@@ -140,7 +140,9 @@
.info-card {
border-radius: 8px;
height: 100%;
- box-shadow: 0px 2px 4px 0px #1e253014, 0px 4px 12px 0px #1e25301f;
+ box-shadow:
+ 0px 2px 4px 0px #1e253014,
+ 0px 4px 12px 0px #1e25301f;
border-top: 8px solid var(--sapphire-blue);
padding: 32px 40px 32px 40px;
@@ -345,7 +347,8 @@
}
video {
- box-shadow: 0px 4px 6px 0px rgba(30, 37, 48, 0.12),
+ box-shadow:
+ 0px 4px 6px 0px rgba(30, 37, 48, 0.12),
0px 8px 16px 0px rgba(30, 37, 48, 0.12);
max-height: 100%;
width: auto;
@@ -998,7 +1001,7 @@
font-size: 1.875rem;
line-height: 1.333;
font-weight: 600;
- quotes: '\201C''\201D'; // override default quotes
+ quotes: '\201C' '\201D'; // override default quotes
padding: unset;
margin: unset;
font-family: 'Noto Sans', sans-serif;
diff --git a/services/web/frontend/stylesheets/bootstrap-5/foundations/elevation.scss b/services/web/frontend/stylesheets/bootstrap-5/foundations/elevation.scss
index c507cb3e64..94ca9c6f93 100644
--- a/services/web/frontend/stylesheets/bootstrap-5/foundations/elevation.scss
+++ b/services/web/frontend/stylesheets/bootstrap-5/foundations/elevation.scss
@@ -5,12 +5,14 @@
// Tooltips, Callouts, Dropdowns, etc.
@mixin shadow-md {
- box-shadow: 0px 4px 24px rgba(30, 37, 48, 0.12),
+ box-shadow:
+ 0px 4px 24px rgba(30, 37, 48, 0.12),
0px 1px 4px rgba(30, 37, 48, 0.08);
}
// Modals, drawers
@mixin shadow-lg {
- box-shadow: 0px 8px 24px rgba(30, 37, 48, 0.16),
+ box-shadow:
+ 0px 8px 24px rgba(30, 37, 48, 0.16),
0px 4px 8px rgba(30, 37, 48, 0.16);
}
diff --git a/services/web/frontend/stylesheets/components/expand-collapse.less b/services/web/frontend/stylesheets/components/expand-collapse.less
index 1a5b6e3eb5..c2f8fa60b5 100644
--- a/services/web/frontend/stylesheets/components/expand-collapse.less
+++ b/services/web/frontend/stylesheets/components/expand-collapse.less
@@ -1,4 +1,6 @@
.expand-collapse-container {
overflow: hidden;
- transition: height 0.15s ease-in-out, width 0.15s ease-in-out;
+ transition:
+ height 0.15s ease-in-out,
+ width 0.15s ease-in-out;
}
diff --git a/services/web/frontend/stylesheets/components/forms.less b/services/web/frontend/stylesheets/components/forms.less
index 5a04165714..220aa35be8 100755
--- a/services/web/frontend/stylesheets/components/forms.less
+++ b/services/web/frontend/stylesheets/components/forms.less
@@ -331,7 +331,8 @@ input[type='checkbox'],
); // Redeclare so transitions work
&:focus {
border-color: darken(@state-danger-text, 10%);
- @shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
+ @shadow:
+ inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 6px lighten(@state-danger-text, 20%);
.box-shadow(@shadow);
}
diff --git a/services/web/frontend/stylesheets/components/input-switch.less b/services/web/frontend/stylesheets/components/input-switch.less
index bc6133f4fc..ecdfa632e7 100644
--- a/services/web/frontend/stylesheets/components/input-switch.less
+++ b/services/web/frontend/stylesheets/components/input-switch.less
@@ -19,7 +19,9 @@
padding: 1px;
background-color: @rp-highlight-blue;
border-radius: 0.875em;
- transition: background 0.15s ease, border-color 0.15s ease;
+ transition:
+ background 0.15s ease,
+ border-color 0.15s ease;
&::before {
content: '';
@@ -31,7 +33,10 @@
top: 1px;
background-color: #fff;
border-radius: 0.875em;
- transition: background-color 0.15s ease, color 0.15s ease, left 0.15s ease;
+ transition:
+ background-color 0.15s ease,
+ color 0.15s ease,
+ left 0.15s ease;
}
}
diff --git a/services/web/frontend/stylesheets/components/navbar.less b/services/web/frontend/stylesheets/components/navbar.less
index d8839911dd..8a89126768 100755
--- a/services/web/frontend/stylesheets/components/navbar.less
+++ b/services/web/frontend/stylesheets/components/navbar.less
@@ -324,7 +324,8 @@
padding: 10px @navbar-padding-horizontal;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
- @shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1),
+ @shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.1),
0 1px 0 rgba(255, 255, 255, 0.1);
.box-shadow(@shadow);
diff --git a/services/web/frontend/stylesheets/components/ui-select.less b/services/web/frontend/stylesheets/components/ui-select.less
index b6231d8b26..562fdfb58d 100644
--- a/services/web/frontend/stylesheets/components/ui-select.less
+++ b/services/web/frontend/stylesheets/components/ui-select.less
@@ -34,7 +34,8 @@
background-color: transparent;
> .btn {
border-color: @input-border-focus;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
+ box-shadow:
+ inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 8px fade(@input-border-focus, 60%);
padding-top: @input-suggestion-v-offset;
}
diff --git a/services/web/frontend/stylesheets/core/type.less b/services/web/frontend/stylesheets/core/type.less
index 15672ec46e..036813d2e0 100755
--- a/services/web/frontend/stylesheets/core/type.less
+++ b/services/web/frontend/stylesheets/core/type.less
@@ -328,7 +328,7 @@ blockquote {
padding: (@line-height-computed / 2) @line-height-computed;
margin: 0 0 @line-height-computed;
font-size: @blockquote-font-size;
- quotes: '\201C''\201D''\2018''\2019';
+ quotes: '\201C' '\201D' '\2018' '\2019';
border-left: 5px solid @blockquote-border-color;
&:before {
content: open-quote;
diff --git a/services/web/frontend/stylesheets/core/variables.less b/services/web/frontend/stylesheets/core/variables.less
index 84afac0c27..ada828214a 100644
--- a/services/web/frontend/stylesheets/core/variables.less
+++ b/services/web/frontend/stylesheets/core/variables.less
@@ -962,7 +962,8 @@
@btn-border-bottom-width: 0;
// Shadows
-@box-shadow: 0px 4px 12px rgba(30, 37, 48, 0.12),
+@box-shadow:
+ 0px 4px 12px rgba(30, 37, 48, 0.12),
0px 2px 4px rgba(30, 37, 48, 0.08);
// Cards
diff --git a/services/web/frontend/stylesheets/variables/all.less b/services/web/frontend/stylesheets/variables/all.less
index 3975d38eed..dd5e9b0d3b 100644
--- a/services/web/frontend/stylesheets/variables/all.less
+++ b/services/web/frontend/stylesheets/variables/all.less
@@ -787,7 +787,8 @@
@btn-secondary-hover-bg-color: @neutral-20;
// Shadows
-@box-shadow: 0px 4px 12px rgba(30, 37, 48, 0.12),
+@box-shadow:
+ 0px 4px 12px rgba(30, 37, 48, 0.12),
0px 2px 4px rgba(30, 37, 48, 0.08);
// Cards
diff --git a/services/web/frontend/stylesheets/vendor/select/select.css b/services/web/frontend/stylesheets/vendor/select/select.css
index 60e1675b94..ce8a9cdc51 100755
--- a/services/web/frontend/stylesheets/vendor/select/select.css
+++ b/services/web/frontend/stylesheets/vendor/select/select.css
@@ -156,7 +156,8 @@ body > .select2-container.open {
text-decoration: none;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
- box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
+ box-shadow:
+ inset 0 1px 1px rgba(0, 0, 0, 0.075),
0 0 8px rgba(102, 175, 233, 0.6);
}
diff --git a/services/web/scripts/analytics/sync_group_subscription_memberships.js b/services/web/scripts/analytics/sync_group_subscription_memberships.js
index 8249177dbb..691a3ec451 100644
--- a/services/web/scripts/analytics/sync_group_subscription_memberships.js
+++ b/services/web/scripts/analytics/sync_group_subscription_memberships.js
@@ -45,9 +45,8 @@ async function checkActiveSubscriptions() {
if (subscriptions.length) {
const groupIds = subscriptions.map(sub => sub._id)
- const bigQueryGroupMemberships = await fetchBigQueryMembershipStatuses(
- groupIds
- )
+ const bigQueryGroupMemberships =
+ await fetchBigQueryMembershipStatuses(groupIds)
const membershipsByGroupId = _.groupBy(
bigQueryGroupMemberships,
'group_id'
@@ -85,9 +84,8 @@ async function checkDeletedSubscriptions() {
if (deletedSubscriptions.length) {
const groupIds = deletedSubscriptions.map(sub => sub._id.toString())
- const bigQueryGroupMemberships = await fetchBigQueryMembershipStatuses(
- groupIds
- )
+ const bigQueryGroupMemberships =
+ await fetchBigQueryMembershipStatuses(groupIds)
const membershipsByGroupId = _.groupBy(
bigQueryGroupMemberships,
diff --git a/services/web/scripts/delete_orphaned_docs_online_check.js b/services/web/scripts/delete_orphaned_docs_online_check.js
index c0a7789d51..a94ff1cce5 100644
--- a/services/web/scripts/delete_orphaned_docs_online_check.js
+++ b/services/web/scripts/delete_orphaned_docs_online_check.js
@@ -68,9 +68,8 @@ async function main() {
new Set(docs.map(doc => doc.project_id.toString()))
).map(id => new ObjectId(id))
console.log('Checking projects', JSON.stringify(projectIds))
- const { nProjectsWithOrphanedDocs, nDeletedDocs } = await processBatch(
- projectIds
- )
+ const { nProjectsWithOrphanedDocs, nDeletedDocs } =
+ await processBatch(projectIds)
nProjectsProcessedTotal += projectIds.length
nProjectsWithOrphanedDocsTotal += nProjectsWithOrphanedDocs
nDeletedDocsTotal += nDeletedDocs
diff --git a/services/web/scripts/restore_soft_deleted_docs.js b/services/web/scripts/restore_soft_deleted_docs.js
index 5ab31f3bef..841407b00f 100644
--- a/services/web/scripts/restore_soft_deleted_docs.js
+++ b/services/web/scripts/restore_soft_deleted_docs.js
@@ -8,9 +8,8 @@ const PROJECT_ID = ARGV.shift()
const FILE_NAMES_TO_RESTORE = ARGV
async function main() {
- const deletedDocs = await DocstoreManager.promises.getAllDeletedDocs(
- PROJECT_ID
- )
+ const deletedDocs =
+ await DocstoreManager.promises.getAllDeletedDocs(PROJECT_ID)
const docsToRestore = deletedDocs.filter(doc =>
FILE_NAMES_TO_RESTORE.includes(doc.name)
)
diff --git a/services/web/scripts/sso_id_migration_check.js b/services/web/scripts/sso_id_migration_check.js
index 822150a91a..20adc37325 100644
--- a/services/web/scripts/sso_id_migration_check.js
+++ b/services/web/scripts/sso_id_migration_check.js
@@ -19,9 +19,8 @@ waitForDb()
})
async function main() {
- const result = await SAMLUserIdMigrationHandler.promises.checkMigration(
- institutionId
- )
+ const result =
+ await SAMLUserIdMigrationHandler.promises.checkMigration(institutionId)
if (emitUsers) {
console.log(
diff --git a/services/web/scripts/sso_id_remove_not_migrated.js b/services/web/scripts/sso_id_remove_not_migrated.js
index 031728fa8f..a63c5c2104 100644
--- a/services/web/scripts/sso_id_remove_not_migrated.js
+++ b/services/web/scripts/sso_id_remove_not_migrated.js
@@ -19,9 +19,8 @@ waitForDb()
})
async function main() {
- const result = await SAMLUserIdMigrationHandler.promises.removeNotMigrated(
- institutionId
- )
+ const result =
+ await SAMLUserIdMigrationHandler.promises.removeNotMigrated(institutionId)
if (emitUsers) {
console.log(
diff --git a/services/web/test/frontend/components/shared/select.spec.tsx b/services/web/test/frontend/components/shared/select.spec.tsx
index 7231a1bd11..594fd3bb5c 100644
--- a/services/web/test/frontend/components/shared/select.spec.tsx
+++ b/services/web/test/frontend/components/shared/select.spec.tsx
@@ -11,7 +11,7 @@ const testData = [1, 2, 3].map(index => ({
sub: `Subtitle ${index}`,
}))
-type RenderProps = Partial> & {
+type RenderProps = Partial> & {
onSubmit?: (formData: object) => void
}
diff --git a/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx b/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx
index 1ce5e43ed6..b65464315c 100644
--- a/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx
+++ b/services/web/test/frontend/features/project-list/components/project-list-root.test.tsx
@@ -803,9 +803,8 @@ describe('', function () {
fireEvent.click(allCheckboxes[1]) // select a project owned by the current user
const actionsToolbar = screen.getAllByRole('toolbar')[0]
- const moreDropdown = await within(
- actionsToolbar
- ).findByText('More')
+ const moreDropdown =
+ await within(actionsToolbar).findByText('More')
fireEvent.click(moreDropdown)
const editButton =
@@ -851,9 +850,8 @@ describe('', function () {
status: 200,
}
)
- const moreDropdown = await within(
- actionsToolbar
- ).findByText('More')
+ const moreDropdown =
+ await within(actionsToolbar).findByText('More')
fireEvent.click(moreDropdown)
const renameButton =
@@ -888,9 +886,8 @@ describe('', function () {
within(table).getByText(newProjectName)
expect(within(table).queryByText(oldName)).to.be.null
- const allCheckboxesInTable = await within(
- table
- ).findAllByRole('checkbox')
+ const allCheckboxesInTable =
+ await within(table).findAllByRole('checkbox')
const allCheckboxesChecked = allCheckboxesInTable.filter(
c => c.checked
)
diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual.spec.tsx
index e732c7f6ef..eb13ffacec 100644
--- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual.spec.tsx
+++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual.spec.tsx
@@ -209,16 +209,19 @@ describe(' in Visual mode', function () {
cy.get('@first-line').should('have.text', `${icon}key `)
})
- forEach([['ref', '🏷']]).it('handles \\%s commands', function (command, icon) {
- cy.get('@first-line').type(`\\${command}{} `)
- cy.get('@first-line').should('have.text', `${icon} `)
- cy.get('@first-line').type('{Backspace}{leftArrow}key')
- cy.get('@first-line').should('have.text', `${icon}{key}`)
- cy.get('@first-line').type('{rightArrow}')
- cy.get('@first-line').should('have.text', `${icon}{key}`)
- cy.get('@first-line').type(' ')
- cy.get('@first-line').should('have.text', `${icon}key `)
- })
+ forEach([['ref', '🏷']]).it(
+ 'handles \\%s commands',
+ function (command, icon) {
+ cy.get('@first-line').type(`\\${command}{} `)
+ cy.get('@first-line').should('have.text', `${icon} `)
+ cy.get('@first-line').type('{Backspace}{leftArrow}key')
+ cy.get('@first-line').should('have.text', `${icon}{key}`)
+ cy.get('@first-line').type('{rightArrow}')
+ cy.get('@first-line').should('have.text', `${icon}{key}`)
+ cy.get('@first-line').type(' ')
+ cy.get('@first-line').should('have.text', `${icon}key `)
+ }
+ )
it('handles \\href command', function () {
cy.get('@first-line').type('\\href{{}https://overleaf.com} ')
diff --git a/services/web/test/unit/src/Institutions/InstitutionHelperTests.js b/services/web/test/unit/src/Institutions/InstitutionHelperTests.js
index edd6669ca1..9de43c4be6 100644
--- a/services/web/test/unit/src/Institutions/InstitutionHelperTests.js
+++ b/services/web/test/unit/src/Institutions/InstitutionHelperTests.js
@@ -1,9 +1,11 @@
const { expect } = require('chai')
const path = require('path')
-const InstitutionsHelper = require(path.join(
- __dirname,
- '/../../../../app/src/Features/Institutions/InstitutionsHelper'
-))
+const InstitutionsHelper = require(
+ path.join(
+ __dirname,
+ '/../../../../app/src/Features/Institutions/InstitutionsHelper'
+ )
+)
describe('InstitutionsHelper', function () {
describe('emailHasLicence', function () {
diff --git a/services/web/test/unit/src/Project/ProjectGetterTests.js b/services/web/test/unit/src/Project/ProjectGetterTests.js
index 10d8de6000..c2e3512ed9 100644
--- a/services/web/test/unit/src/Project/ProjectGetterTests.js
+++ b/services/web/test/unit/src/Project/ProjectGetterTests.js
@@ -440,9 +440,8 @@ describe('ProjectGetter', function () {
})
it('should pass the found projects to the callback', async function () {
- const docs = await this.ProjectGetter.promises.getUsersDeletedProjects(
- 'giraffe'
- )
+ const docs =
+ await this.ProjectGetter.promises.getUsersDeletedProjects('giraffe')
expect(docs).to.deep.equal([this.deletedProject])
})
})
diff --git a/services/web/test/unit/src/Subscription/SubscriptionGroupHandlerTests.js b/services/web/test/unit/src/Subscription/SubscriptionGroupHandlerTests.js
index 81d898101b..d9f81045a5 100644
--- a/services/web/test/unit/src/Subscription/SubscriptionGroupHandlerTests.js
+++ b/services/web/test/unit/src/Subscription/SubscriptionGroupHandlerTests.js
@@ -160,9 +160,8 @@ describe('SubscriptionGroupHandler', function () {
})
describe('for nonexistent subscriptions', function () {
it('should return undefined', async function () {
- const count = await this.Handler.promises.getTotalConfirmedUsersInGroup(
- 'fake-id'
- )
+ const count =
+ await this.Handler.promises.getTotalConfirmedUsersInGroup('fake-id')
expect(count).not.to.exist
})
})
diff --git a/services/web/test/unit/src/Uploads/FileSystemImportManagerTests.js b/services/web/test/unit/src/Uploads/FileSystemImportManagerTests.js
index fb0a2ad2be..d42388bf04 100644
--- a/services/web/test/unit/src/Uploads/FileSystemImportManagerTests.js
+++ b/services/web/test/unit/src/Uploads/FileSystemImportManagerTests.js
@@ -64,9 +64,8 @@ describe('FileSystemImportManager', function () {
},
symlink: mockFs.symlink({ path: 'import-test' }),
})
- this.entries = await this.FileSystemImportManager.promises.importDir(
- 'import-test'
- )
+ this.entries =
+ await this.FileSystemImportManager.promises.importDir('import-test')
this.projectPaths = this.entries.map(x => x.projectPath)
})
diff --git a/services/web/types/utils.ts b/services/web/types/utils.ts
index 4bdb852937..52c505dbac 100644
--- a/services/web/types/utils.ts
+++ b/services/web/types/utils.ts
@@ -10,10 +10,10 @@ type DeepReadonlyObject = {
export type DeepReadonly = T extends (infer R)[]
? DeepReadonlyArray
: T extends (...args: any[]) => void
- ? T
- : T extends object
- ? DeepReadonlyObject
- : T
+ ? T
+ : T extends object
+ ? DeepReadonlyObject
+ : T
export type DeepPartial = Partial<{ [P in keyof T]: DeepPartial }>