overleaf/services/web/app/src/infrastructure/Modules.js
Eric Mc Sween 1c0b897835 Merge pull request #3638 from overleaf/em-dropbox-duplicate-projects
Unlink Dropbox when two projects have the same name

GitOrigin-RevId: b16dbeb6841eaebd8553884eebc87e681d17a9c8
2021-02-18 03:05:12 +00:00

151 lines
3.5 KiB
JavaScript

const fs = require('fs')
const Path = require('path')
const pug = require('pug')
const async = require('async')
const { promisify } = require('util')
const Settings = require('settings-sharelatex')
const MODULE_BASE_PATH = Path.resolve(__dirname + '/../../../modules')
const _modules = []
const _hooks = {}
let _viewIncludes = {}
function loadModules() {
for (let moduleName of fs.readdirSync(MODULE_BASE_PATH)) {
if (fs.existsSync(Path.join(MODULE_BASE_PATH, moduleName, 'index.js'))) {
const loadedModule = require(Path.join(
MODULE_BASE_PATH,
moduleName,
'index'
))
loadedModule.name = moduleName
_modules.push(loadedModule)
}
}
attachHooks()
}
function applyRouter(webRouter, privateApiRouter, publicApiRouter) {
for (const module of _modules) {
if (module.router && module.router.apply) {
module.router.apply(webRouter, privateApiRouter, publicApiRouter)
}
}
}
function applyNonCsrfRouter(webRouter, privateApiRouter, publicApiRouter) {
for (let module of _modules) {
if (module.nonCsrfRouter != null) {
module.nonCsrfRouter.apply(webRouter, privateApiRouter, publicApiRouter)
}
if (module.router && module.router.applyNonCsrfRouter) {
module.router.applyNonCsrfRouter(
webRouter,
privateApiRouter,
publicApiRouter
)
}
}
}
function loadViewIncludes(app) {
_viewIncludes = {}
for (const module of _modules) {
const object = module.viewIncludes || {}
for (let view in object) {
const partial = object[view]
if (!_viewIncludes[view]) {
_viewIncludes[view] = []
}
const filePath = Path.join(
MODULE_BASE_PATH,
module.name,
'app/views',
partial + '.pug'
)
_viewIncludes[view].push(
pug.compileFile(filePath, {
doctype: 'html',
compileDebug: Settings.debugPugTemplates
})
)
}
}
}
function moduleIncludes(view, locals) {
const compiledPartials = _viewIncludes[view] || []
let html = ''
for (let compiledPartial of compiledPartials) {
html += compiledPartial(locals)
}
return html
}
function moduleIncludesAvailable(view) {
return (_viewIncludes[view] || []).length > 0
}
function linkedFileAgentsIncludes() {
const agents = {}
for (let module of _modules) {
for (let name in module.linkedFileAgents) {
const agentFunction = module.linkedFileAgents[name]
agents[name] = agentFunction()
}
}
return agents
}
function attachHooks() {
for (var module of _modules) {
if (module.hooks != null) {
for (let hook in module.hooks) {
const method = module.hooks[hook]
attachHook(hook, method)
}
}
}
}
function attachHook(name, method) {
if (_hooks[name] == null) {
_hooks[name] = []
}
_hooks[name].push(method)
}
function fireHook(name, ...rest) {
const adjustedLength = Math.max(rest.length, 1)
const args = rest.slice(0, adjustedLength - 1)
const callback = rest[adjustedLength - 1]
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)
})
}
module.exports = {
applyNonCsrfRouter,
applyRouter,
linkedFileAgentsIncludes,
loadViewIncludes,
moduleIncludes,
moduleIncludesAvailable,
hooks: {
attach: attachHook,
fire: fireHook
},
promises: {
hooks: {
fire: promisify(fireHook)
}
}
}
loadModules()