Merge pull request #20415 from overleaf/tm-async-hooks

Proposal: Add promise interface for attaching module hooks and switch methods to be "Promise-first"
GitOrigin-RevId: 6740c18b75ebca79c24aa8b9867c8127b381b695
This commit is contained in:
Thomas 2024-10-28 17:08:55 +01:00 committed by Copybot
parent ef90950cd3
commit 74bee7e30b

View file

@ -1,7 +1,6 @@
const fs = require('fs') const fs = require('fs')
const Path = require('path') const Path = require('path')
const async = require('async') const { promisify, callbackify } = require('util')
const { promisify } = require('util')
const Settings = require('@overleaf/settings') const Settings = require('@overleaf/settings')
const Views = require('./Views') const Views = require('./Views')
const _ = require('lodash') const _ = require('lodash')
@ -147,10 +146,15 @@ async function linkedFileAgentsIncludes() {
async function attachHooks() { async function attachHooks() {
for (const module of await modules()) { for (const module of await modules()) {
for (const hook in module.hooks || {}) { const { promises, ...hooks } = module.hooks || {}
const method = module.hooks[hook] for (const hook in promises || {}) {
const method = promises[hook]
attachHook(hook, method) attachHook(hook, method)
} }
for (const hook in hooks || {}) {
const method = hooks[hook]
attachHook(hook, promisify(method))
}
} }
} }
@ -173,32 +177,19 @@ async function attachMiddleware() {
} }
} }
function fireHook(name, ...rest) { async function fireHook(name, ...args) {
const adjustedLength = Math.max(rest.length, 1)
const args = rest.slice(0, adjustedLength - 1)
const callback = rest[adjustedLength - 1]
function fire() {
const methods = _hooks[name] || []
const callMethods = methods.map(method => cb => method(...args, cb))
async.series(callMethods, function (error, results) {
if (error) {
return callback(error)
}
callback(null, results)
})
}
// ensure that modules are loaded if we need to fire a hook // ensure that modules are loaded if we need to fire a hook
// this can happen if a script calls a method that fires a hook // this can happen if a script calls a method that fires a hook
if (!_modulesLoaded) { if (!_modulesLoaded) {
loadModules() await loadModules()
.then(() => {
fire()
})
.catch(err => callback(err))
} else {
fire()
} }
const methods = _hooks[name] || []
const results = []
for (const method of methods) {
const result = await method(...args)
results.push(result)
}
return results
} }
async function getMiddleware(name) { async function getMiddleware(name) {
@ -220,12 +211,12 @@ module.exports = {
start, start,
hooks: { hooks: {
attach: attachHook, attach: attachHook,
fire: fireHook, fire: callbackify(fireHook),
}, },
middleware: getMiddleware, middleware: getMiddleware,
promises: { promises: {
hooks: { hooks: {
fire: promisify(fireHook), fire: fireHook,
}, },
}, },
} }