Sfoglia il codice sorgente

Migrate Features to ES modules

GitOrigin-RevId: 4e9d3176b4b5a5504afc102e569a27d7788864a3
Andrew Rumble 1 anno fa
parent
commit
c6c62088cc
70 ha cambiato i file con 619 aggiunte e 609 eliminazioni
  1. 2 2
      services/web/app.mjs
  2. 7 7
      services/web/app/src/Features/Analytics/AnalyticsController.mjs
  3. 4 4
      services/web/app/src/Features/Analytics/AnalyticsProxy.mjs
  4. 6 6
      services/web/app/src/Features/Analytics/AnalyticsRouter.mjs
  5. 9 9
      services/web/app/src/Features/Analytics/AnalyticsUTMTrackingMiddleware.mjs
  6. 8 8
      services/web/app/src/Features/BetaProgram/BetaProgramController.mjs
  7. 5 5
      services/web/app/src/Features/BetaProgram/BetaProgramHandler.mjs
  8. 23 21
      services/web/app/src/Features/Collaborators/CollaboratorsController.mjs
  9. 5 5
      services/web/app/src/Features/Collaborators/CollaboratorsEmailHandler.mjs
  10. 21 21
      services/web/app/src/Features/Collaborators/CollaboratorsInviteController.mjs
  11. 16 16
      services/web/app/src/Features/Collaborators/CollaboratorsInviteHandler.mjs
  12. 11 11
      services/web/app/src/Features/Collaborators/CollaboratorsRouter.mjs
  13. 6 6
      services/web/app/src/Features/Contacts/ContactController.mjs
  14. 5 5
      services/web/app/src/Features/Contacts/ContactRouter.mjs
  15. 4 3
      services/web/app/src/Features/Cooldown/CooldownMiddleware.mjs
  16. 6 6
      services/web/app/src/Features/DocumentUpdater/DocumentUpdaterController.mjs
  17. 10 10
      services/web/app/src/Features/Documents/DocumentController.mjs
  18. 7 7
      services/web/app/src/Features/Downloads/ProjectDownloadsController.mjs
  19. 7 7
      services/web/app/src/Features/Downloads/ProjectZipStreamManager.mjs
  20. 7 7
      services/web/app/src/Features/Editor/EditorRouter.mjs
  21. 5 4
      services/web/app/src/Features/Exports/ExportsController.mjs
  22. 12 13
      services/web/app/src/Features/Exports/ExportsHandler.mjs
  23. 6 7
      services/web/app/src/Features/FileStore/FileStoreController.mjs
  24. 9 8
      services/web/app/src/Features/HealthCheck/HealthCheckController.mjs
  25. 11 13
      services/web/app/src/Features/History/HistoryRangesSupportMigration.mjs
  26. 2 2
      services/web/app/src/Features/InactiveData/InactiveProjectController.mjs
  27. 20 20
      services/web/app/src/Features/LinkedFiles/LinkedFilesController.mjs
  28. 7 7
      services/web/app/src/Features/LinkedFiles/LinkedFilesRouter.mjs
  29. 11 11
      services/web/app/src/Features/LinkedFiles/ProjectOutputFileAgent.mjs
  30. 9 9
      services/web/app/src/Features/LinkedFiles/UrlAgent.mjs
  31. 6 6
      services/web/app/src/Features/Metadata/MetaController.mjs
  32. 5 5
      services/web/app/src/Features/Metadata/MetaHandler.mjs
  33. 1 1
      services/web/app/src/Features/Metadata/packageMapping.mjs
  34. 4 4
      services/web/app/src/Features/Notifications/NotificationsController.mjs
  35. 11 11
      services/web/app/src/Features/PasswordReset/PasswordResetController.mjs
  36. 11 10
      services/web/app/src/Features/PasswordReset/PasswordResetHandler.mjs
  37. 7 7
      services/web/app/src/Features/PasswordReset/PasswordResetRouter.mjs
  38. 2 2
      services/web/app/src/Features/Project/DocLinesComparitor.mjs
  39. 4 3
      services/web/app/src/Features/Project/ProjectApiController.mjs
  40. 30 29
      services/web/app/src/Features/Project/ProjectListController.mjs
  41. 1 1
      services/web/app/src/Features/Referal/ReferalConnect.mjs
  42. 3 3
      services/web/app/src/Features/Referal/ReferalController.mjs
  43. 3 3
      services/web/app/src/Features/Referal/ReferalHandler.mjs
  44. 5 6
      services/web/app/src/Features/References/ReferencesController.mjs
  45. 14 13
      services/web/app/src/Features/References/ReferencesHandler.mjs
  46. 6 6
      services/web/app/src/Features/Spelling/SpellingController.mjs
  47. 11 12
      services/web/app/src/Features/StaticPages/HomeController.mjs
  48. 3 2
      services/web/app/src/Features/StaticPages/StaticPageHelpers.mjs
  49. 4 3
      services/web/app/src/Features/StaticPages/StaticPagesRouter.mjs
  50. 1 4
      services/web/app/src/Features/StaticPages/UniversityController.mjs
  51. 10 9
      services/web/app/src/Features/Subscription/SubscriptionGroupController.mjs
  52. 10 10
      services/web/app/src/Features/Subscription/SubscriptionRouter.mjs
  53. 18 18
      services/web/app/src/Features/Subscription/TeamInvitesController.mjs
  54. 4 4
      services/web/app/src/Features/Survey/SurveyCache.mjs
  55. 6 5
      services/web/app/src/Features/Survey/SurveyHandler.mjs
  56. 5 5
      services/web/app/src/Features/Tags/TagsController.mjs
  57. 14 14
      services/web/app/src/Features/ThirdPartyDataStore/TpdsController.mjs
  58. 4 4
      services/web/app/src/Features/ThirdPartyDataStore/TpdsQueueManager.mjs
  59. 14 14
      services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.mjs
  60. 25 28
      services/web/app/src/Features/TokenAccess/TokenAccessController.mjs
  61. 4 4
      services/web/app/src/Features/TokenAccess/TokenAccessRouter.mjs
  62. 4 4
      services/web/app/src/Features/Tutorial/TutorialController.mjs
  63. 18 16
      services/web/app/src/Features/Uploads/ProjectUploadController.mjs
  64. 7 7
      services/web/app/src/Features/Uploads/UploadsRouter.mjs
  65. 15 15
      services/web/app/src/Features/User/UserPagesController.mjs
  66. 11 11
      services/web/app/src/Features/UserMembership/UserMembershipController.mjs
  67. 7 7
      services/web/app/src/Features/UserMembership/UserMembershipRouter.mjs
  68. 5 5
      services/web/app/src/Features/V1/V1Handler.mjs
  69. 25 22
      services/web/test/unit/src/BetaProgram/BetaProgramControllerTests.mjs
  70. 20 16
      services/web/test/unit/src/BetaProgram/BetaProgramHandlerTests.mjs

+ 2 - 2
services/web/app.mjs

@@ -6,12 +6,12 @@ import metrics from '@overleaf/metrics'
 import Settings from '@overleaf/settings'
 import logger from '@overleaf/logger'
 import PlansLocator from './app/src/Features/Subscription/PlansLocator.js'
-import SiteAdminHandler from './app/src/infrastructure/SiteAdminHandler.js'
+import SiteAdminHandler from './app/src/infrastructure/SiteAdminHandler.mjs'
 
 import http from 'node:http'
 import https from 'node:https'
 
-import * as Serializers from './app/src/infrastructure/LoggerSerializers.js'
+import * as Serializers from './app/src/infrastructure/LoggerSerializers.mjs'
 
 import Server from './app/src/infrastructure/Server.mjs'
 import QueueWorkers from './app/src/infrastructure/QueueWorkers.js'

+ 7 - 7
services/web/app/src/Features/Analytics/AnalyticsController.js → services/web/app/src/Features/Analytics/AnalyticsController.mjs

@@ -1,9 +1,9 @@
-const metrics = require('@overleaf/metrics')
-const AnalyticsManager = require('./AnalyticsManager')
-const SessionManager = require('../Authentication/SessionManager')
-const GeoIpLookup = require('../../infrastructure/GeoIpLookup')
-const Features = require('../../infrastructure/Features')
-const { expressify } = require('@overleaf/promise-utils')
+import metrics from '@overleaf/metrics'
+import AnalyticsManager from './AnalyticsManager.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import GeoIpLookup from '../../infrastructure/GeoIpLookup.js'
+import Features from '../../infrastructure/Features.js'
+import { expressify } from '@overleaf/promise-utils'
 
 async function updateEditingSession(req, res, next) {
   if (!Features.hasFeature('analytics')) {
@@ -46,7 +46,7 @@ function recordEvent(req, res, next) {
   res.sendStatus(202)
 }
 
-module.exports = {
+export default {
   updateEditingSession: expressify(updateEditingSession),
   recordEvent,
 }

+ 4 - 4
services/web/app/src/Features/Analytics/AnalyticsProxy.js → services/web/app/src/Features/Analytics/AnalyticsProxy.mjs

@@ -1,8 +1,8 @@
-const settings = require('@overleaf/settings')
-const Errors = require('../Errors/Errors')
-const httpProxy = require('express-http-proxy')
+import settings from '@overleaf/settings'
+import Errors from '../Errors/Errors.js'
+import httpProxy from 'express-http-proxy'
 
-module.exports = {
+export default {
   call(basePath) {
     if (!settings.apis.analytics) {
       return (req, res, next) =>

+ 6 - 6
services/web/app/src/Features/Analytics/AnalyticsRouter.js → services/web/app/src/Features/Analytics/AnalyticsRouter.mjs

@@ -1,8 +1,8 @@
-const AuthenticationController = require('./../Authentication/AuthenticationController')
-const AnalyticsController = require('./AnalyticsController')
-const AnalyticsProxy = require('./AnalyticsProxy')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
+import AuthenticationController from './../Authentication/AuthenticationController.js'
+import AnalyticsController from './AnalyticsController.mjs'
+import AnalyticsProxy from './AnalyticsProxy.mjs'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
 
 const rateLimiters = {
   recordEvent: new RateLimiter('analytics-record-event', {
@@ -19,7 +19,7 @@ const rateLimiters = {
   ),
 }
 
-module.exports = {
+export default {
   apply(webRouter, privateApiRouter, publicApiRouter) {
     webRouter.post(
       '/event/:event([a-z0-9-_]+)',

+ 9 - 9
services/web/app/src/Features/Analytics/AnalyticsUTMTrackingMiddleware.js → services/web/app/src/Features/Analytics/AnalyticsUTMTrackingMiddleware.mjs

@@ -1,11 +1,11 @@
-const _ = require('lodash')
-const RequestHelper = require('./RequestHelper')
-const AnalyticsManager = require('./AnalyticsManager')
-const querystring = require('querystring')
-const { URL } = require('url')
-const Settings = require('@overleaf/settings')
-const OError = require('@overleaf/o-error')
-const logger = require('@overleaf/logger')
+import _ from 'lodash'
+import RequestHelper from './RequestHelper.js'
+import AnalyticsManager from './AnalyticsManager.js'
+import querystring from 'querystring'
+import { URL } from 'url'
+import Settings from '@overleaf/settings'
+import OError from '@overleaf/o-error'
+import logger from '@overleaf/logger'
 
 function recordUTMTags() {
   return function (req, res, next) {
@@ -53,6 +53,6 @@ function recordUTMTags() {
   }
 }
 
-module.exports = {
+export default {
   recordUTMTags,
 }

+ 8 - 8
services/web/app/src/Features/BetaProgram/BetaProgramController.js → services/web/app/src/Features/BetaProgram/BetaProgramController.mjs

@@ -1,10 +1,10 @@
-const BetaProgramHandler = require('./BetaProgramHandler')
-const OError = require('@overleaf/o-error')
-const UserGetter = require('../User/UserGetter')
-const logger = require('@overleaf/logger')
-const SessionManager = require('../Authentication/SessionManager')
-const SplitTestSessionHandler = require('../SplitTests/SplitTestSessionHandler')
-const { expressify } = require('@overleaf/promise-utils')
+import BetaProgramHandler from './BetaProgramHandler.mjs'
+import OError from '@overleaf/o-error'
+import UserGetter from '../User/UserGetter.js'
+import logger from '@overleaf/logger'
+import SessionManager from '../Authentication/SessionManager.js'
+import SplitTestSessionHandler from '../SplitTests/SplitTestSessionHandler.js'
+import { expressify } from '@overleaf/promise-utils'
 
 async function optIn(req, res) {
   const userId = SessionManager.getLoggedInUserId(req.session)
@@ -50,7 +50,7 @@ async function optInPage(req, res) {
   })
 }
 
-module.exports = {
+export default {
   optIn: expressify(optIn),
   optOut: expressify(optOut),
   optInPage: expressify(optInPage),

+ 5 - 5
services/web/app/src/Features/BetaProgram/BetaProgramHandler.js → services/web/app/src/Features/BetaProgram/BetaProgramHandler.mjs

@@ -1,7 +1,7 @@
-const { callbackify } = require('util')
-const metrics = require('@overleaf/metrics')
-const UserUpdater = require('../User/UserUpdater')
-const AnalyticsManager = require('../Analytics/AnalyticsManager')
+import { callbackify } from 'util'
+import metrics from '@overleaf/metrics'
+import UserUpdater from '../User/UserUpdater.js'
+import AnalyticsManager from '../Analytics/AnalyticsManager.js'
 
 async function optIn(userId) {
   await UserUpdater.promises.updateUser(userId, { $set: { betaProgram: true } })
@@ -25,7 +25,7 @@ async function optOut(userId) {
   )
 }
 
-module.exports = {
+export default {
   optIn: callbackify(optIn),
   optOut: callbackify(optOut),
   promises: {

+ 23 - 21
services/web/app/src/Features/Collaborators/CollaboratorsController.js → services/web/app/src/Features/Collaborators/CollaboratorsController.mjs

@@ -1,24 +1,26 @@
-const OError = require('@overleaf/o-error')
-const HttpErrorHandler = require('../../Features/Errors/HttpErrorHandler')
-const { ObjectId } = require('mongodb-legacy')
-const CollaboratorsHandler = require('./CollaboratorsHandler')
-const CollaboratorsGetter = require('./CollaboratorsGetter')
-const OwnershipTransferHandler = require('./OwnershipTransferHandler')
-const SessionManager = require('../Authentication/SessionManager')
-const EditorRealTimeController = require('../Editor/EditorRealTimeController')
-const TagsHandler = require('../Tags/TagsHandler')
-const Errors = require('../Errors/Errors')
-const logger = require('@overleaf/logger')
-const { expressify } = require('@overleaf/promise-utils')
-const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
-const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
-const ProjectAuditLogHandler = require('../Project/ProjectAuditLogHandler')
-const ProjectGetter = require('../Project/ProjectGetter')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
-const LimitationsManager = require('../Subscription/LimitationsManager')
-const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
-
-module.exports = {
+import OError from '@overleaf/o-error'
+import HttpErrorHandler from '../../Features/Errors/HttpErrorHandler.js'
+import mongodb from 'mongodb-legacy'
+import CollaboratorsHandler from './CollaboratorsHandler.js'
+import CollaboratorsGetter from './CollaboratorsGetter.js'
+import OwnershipTransferHandler from './OwnershipTransferHandler.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
+import TagsHandler from '../Tags/TagsHandler.js'
+import Errors from '../Errors/Errors.js'
+import logger from '@overleaf/logger'
+import { expressify } from '@overleaf/promise-utils'
+import { hasAdminAccess } from '../Helpers/AdminAuthorizationHelper.js'
+import TokenAccessHandler from '../TokenAccess/TokenAccessHandler.js'
+import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
+import LimitationsManager from '../Subscription/LimitationsManager.js'
+import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
+
+const ObjectId = mongodb.ObjectId
+
+export default {
   removeUserFromProject: expressify(removeUserFromProject),
   removeSelfFromProject: expressify(removeSelfFromProject),
   getAllMembers: expressify(getAllMembers),

+ 5 - 5
services/web/app/src/Features/Collaborators/CollaboratorsEmailHandler.js → services/web/app/src/Features/Collaborators/CollaboratorsEmailHandler.mjs

@@ -1,7 +1,7 @@
-const { callbackify } = require('util')
-const { Project } = require('../../models/Project')
-const EmailHandler = require('../Email/EmailHandler')
-const Settings = require('@overleaf/settings')
+import { callbackify } from 'util'
+import { Project } from '../../models/Project.js'
+import EmailHandler from '../Email/EmailHandler.js'
+import Settings from '@overleaf/settings'
 
 const CollaboratorsEmailHandler = {
   _buildInviteUrl(project, invite) {
@@ -28,7 +28,7 @@ const CollaboratorsEmailHandler = {
   },
 }
 
-module.exports = {
+export default {
   promises: CollaboratorsEmailHandler,
   notifyUserOfProjectInvite: callbackify(
     CollaboratorsEmailHandler.notifyUserOfProjectInvite

+ 21 - 21
services/web/app/src/Features/Collaborators/CollaboratorsInviteController.js → services/web/app/src/Features/Collaborators/CollaboratorsInviteController.mjs

@@ -1,23 +1,23 @@
-const { callbackify } = require('util')
-const ProjectGetter = require('../Project/ProjectGetter')
-const LimitationsManager = require('../Subscription/LimitationsManager')
-const UserGetter = require('../User/UserGetter')
-const CollaboratorsGetter = require('./CollaboratorsGetter')
-const CollaboratorsInviteHandler = require('./CollaboratorsInviteHandler')
-const CollaboratorsInviteGetter = require('./CollaboratorsInviteGetter')
-const logger = require('@overleaf/logger')
-const Settings = require('@overleaf/settings')
-const EmailHelper = require('../Helpers/EmailHelper')
-const EditorRealTimeController = require('../Editor/EditorRealTimeController')
-const AnalyticsManager = require('../Analytics/AnalyticsManager')
-const SessionManager = require('../Authentication/SessionManager')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const { expressify } = require('@overleaf/promise-utils')
-const ProjectAuditLogHandler = require('../Project/ProjectAuditLogHandler')
-const Errors = require('../Errors/Errors')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
-const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
+import { callbackify } from 'util'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import LimitationsManager from '../Subscription/LimitationsManager.js'
+import UserGetter from '../User/UserGetter.js'
+import CollaboratorsGetter from './CollaboratorsGetter.js'
+import CollaboratorsInviteHandler from './CollaboratorsInviteHandler.mjs'
+import CollaboratorsInviteGetter from './CollaboratorsInviteGetter.js'
+import logger from '@overleaf/logger'
+import Settings from '@overleaf/settings'
+import EmailHelper from '../Helpers/EmailHelper.js'
+import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
+import AnalyticsManager from '../Analytics/AnalyticsManager.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import { expressify } from '@overleaf/promise-utils'
+import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
+import Errors from '../Errors/Errors.js'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
+import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
 
 // This rate limiter allows a different number of requests depending on the
 // number of callaborators a user is allowed. This is implemented by providing
@@ -398,7 +398,7 @@ const CollaboratorsInviteController = {
   },
 }
 
-module.exports = {
+export default {
   promises: CollaboratorsInviteController,
   getAllInvites: expressify(CollaboratorsInviteController.getAllInvites),
   inviteToProject: expressify(CollaboratorsInviteController.inviteToProject),

+ 16 - 16
services/web/app/src/Features/Collaborators/CollaboratorsInviteHandler.js → services/web/app/src/Features/Collaborators/CollaboratorsInviteHandler.mjs

@@ -1,18 +1,18 @@
-const { callbackify } = require('util')
-const { ProjectInvite } = require('../../models/ProjectInvite')
-const logger = require('@overleaf/logger')
-const CollaboratorsEmailHandler = require('./CollaboratorsEmailHandler')
-const CollaboratorsHandler = require('./CollaboratorsHandler')
-const CollaboratorsInviteGetter = require('./CollaboratorsInviteGetter')
-const CollaboratorsInviteHelper = require('./CollaboratorsInviteHelper')
-const UserGetter = require('../User/UserGetter')
-const ProjectGetter = require('../Project/ProjectGetter')
-const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
-const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
-const LimitationsManager = require('../Subscription/LimitationsManager')
-const ProjectAuditLogHandler = require('../Project/ProjectAuditLogHandler')
-const _ = require('lodash')
+import { callbackify } from 'util'
+import { ProjectInvite } from '../../models/ProjectInvite.js'
+import logger from '@overleaf/logger'
+import CollaboratorsEmailHandler from './CollaboratorsEmailHandler.mjs'
+import CollaboratorsHandler from './CollaboratorsHandler.js'
+import CollaboratorsInviteGetter from './CollaboratorsInviteGetter.js'
+import CollaboratorsInviteHelper from './CollaboratorsInviteHelper.js'
+import UserGetter from '../User/UserGetter.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import NotificationsBuilder from '../Notifications/NotificationsBuilder.js'
+import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
+import LimitationsManager from '../Subscription/LimitationsManager.js'
+import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
+import _ from 'lodash'
 
 const CollaboratorsInviteHandler = {
   async _trySendInviteNotification(projectId, sendingUser, invite) {
@@ -198,7 +198,7 @@ const CollaboratorsInviteHandler = {
   },
 }
 
-module.exports = {
+export default {
   promises: CollaboratorsInviteHandler,
   inviteToProject: callbackify(CollaboratorsInviteHandler.inviteToProject),
   revokeInviteForUser: callbackify(

+ 11 - 11
services/web/app/src/Features/Collaborators/CollaboratorsRouter.js → services/web/app/src/Features/Collaborators/CollaboratorsRouter.mjs

@@ -1,13 +1,13 @@
-const CollaboratorsController = require('./CollaboratorsController')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const AuthorizationMiddleware = require('../Authorization/AuthorizationMiddleware')
-const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
-const CollaboratorsInviteController = require('./CollaboratorsInviteController')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
-const CaptchaMiddleware = require('../Captcha/CaptchaMiddleware')
-const AnalyticsRegistrationSourceMiddleware = require('../Analytics/AnalyticsRegistrationSourceMiddleware')
-const { Joi, validate } = require('../../infrastructure/Validation')
+import CollaboratorsController from './CollaboratorsController.mjs'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import AuthorizationMiddleware from '../Authorization/AuthorizationMiddleware.js'
+import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
+import CollaboratorsInviteController from './CollaboratorsInviteController.mjs'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
+import CaptchaMiddleware from '../Captcha/CaptchaMiddleware.js'
+import AnalyticsRegistrationSourceMiddleware from '../Analytics/AnalyticsRegistrationSourceMiddleware.js'
+import { Joi, validate } from '../../infrastructure/Validation.js'
 
 const rateLimiters = {
   inviteToProjectByProjectId: new RateLimiter(
@@ -32,7 +32,7 @@ const rateLimiters = {
   }),
 }
 
-module.exports = {
+export default {
   apply(webRouter) {
     webRouter.post(
       '/project/:Project_id/leave',

+ 6 - 6
services/web/app/src/Features/Contacts/ContactController.js → services/web/app/src/Features/Contacts/ContactController.mjs

@@ -1,8 +1,8 @@
-const SessionManager = require('../Authentication/SessionManager')
-const ContactManager = require('./ContactManager')
-const UserGetter = require('../User/UserGetter')
-const Modules = require('../../infrastructure/Modules')
-const { expressify } = require('@overleaf/promise-utils')
+import SessionManager from '../Authentication/SessionManager.js'
+import ContactManager from './ContactManager.js'
+import UserGetter from '../User/UserGetter.js'
+import Modules from '../../infrastructure/Modules.js'
+import { expressify } from '@overleaf/promise-utils'
 
 function _formatContact(contact) {
   return {
@@ -55,6 +55,6 @@ async function getContacts(req, res) {
   })
 }
 
-module.exports = {
+export default {
   getContacts: expressify(getContacts),
 }

+ 5 - 5
services/web/app/src/Features/Contacts/ContactRouter.js → services/web/app/src/Features/Contacts/ContactRouter.mjs

@@ -1,7 +1,7 @@
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const SessionManager = require('../Authentication/SessionManager')
-const ContactController = require('./ContactController')
-const Settings = require('@overleaf/settings')
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import ContactController from './ContactController.mjs'
+import Settings from '@overleaf/settings'
 
 function contactsAuthenticationMiddleware() {
   if (!Settings.allowAnonymousReadAndWriteSharing) {
@@ -17,7 +17,7 @@ function contactsAuthenticationMiddleware() {
   }
 }
 
-module.exports = {
+export default {
   apply(webRouter) {
     webRouter.get(
       '/user/contacts',

+ 4 - 3
services/web/app/src/Features/Cooldown/CooldownMiddleware.js → services/web/app/src/Features/Cooldown/CooldownMiddleware.mjs

@@ -10,11 +10,12 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import CooldownManager from './CooldownManager.js'
+import logger from '@overleaf/logger'
+
 let CooldownMiddleware
-const CooldownManager = require('./CooldownManager')
-const logger = require('@overleaf/logger')
 
-module.exports = CooldownMiddleware = {
+export default CooldownMiddleware = {
   freezeProject(req, res, next) {
     const projectId = req.params.Project_id
     if (projectId == null) {

+ 6 - 6
services/web/app/src/Features/DocumentUpdater/DocumentUpdaterController.js → services/web/app/src/Features/DocumentUpdater/DocumentUpdaterController.mjs

@@ -1,8 +1,8 @@
-const logger = require('@overleaf/logger')
-const DocumentUpdaterHandler = require('./DocumentUpdaterHandler')
-const ProjectLocator = require('../Project/ProjectLocator')
-const { plainTextResponse } = require('../../infrastructure/Response')
-const { expressify } = require('@overleaf/promise-utils')
+import logger from '@overleaf/logger'
+import DocumentUpdaterHandler from './DocumentUpdaterHandler.js'
+import ProjectLocator from '../Project/ProjectLocator.js'
+import { plainTextResponse } from '../../infrastructure/Response.js'
+import { expressify } from '@overleaf/promise-utils'
 
 async function getDoc(req, res) {
   const projectId = req.params.Project_id
@@ -42,7 +42,7 @@ async function getDoc(req, res) {
   }
 }
 
-module.exports = {
+export default {
   getDoc: expressify(getDoc),
   promises: {
     getDoc,

+ 10 - 10
services/web/app/src/Features/Documents/DocumentController.js → services/web/app/src/Features/Documents/DocumentController.mjs

@@ -1,12 +1,12 @@
-const ChatApiHandler = require('../Chat/ChatApiHandler')
-const ProjectGetter = require('../Project/ProjectGetter')
-const ProjectLocator = require('../Project/ProjectLocator')
-const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
-const ProjectEntityUpdateHandler = require('../Project/ProjectEntityUpdateHandler')
-const logger = require('@overleaf/logger')
-const _ = require('lodash')
-const { plainTextResponse } = require('../../infrastructure/Response')
-const { expressify } = require('@overleaf/promise-utils')
+import ChatApiHandler from '../Chat/ChatApiHandler.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import ProjectLocator from '../Project/ProjectLocator.js'
+import ProjectEntityHandler from '../Project/ProjectEntityHandler.js'
+import ProjectEntityUpdateHandler from '../Project/ProjectEntityUpdateHandler.js'
+import logger from '@overleaf/logger'
+import _ from 'lodash'
+import { plainTextResponse } from '../../infrastructure/Response.js'
+import { expressify } from '@overleaf/promise-utils'
 
 async function getDocument(req, res) {
   const { Project_id: projectId, doc_id: docId } = req.params
@@ -89,7 +89,7 @@ async function setDocument(req, res) {
   res.json(result)
 }
 
-module.exports = {
+export default {
   getDocument: expressify(getDocument),
   setDocument: expressify(setDocument),
 }

+ 7 - 7
services/web/app/src/Features/Downloads/ProjectDownloadsController.js → services/web/app/src/Features/Downloads/ProjectDownloadsController.mjs

@@ -10,15 +10,15 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import Metrics from '@overleaf/metrics'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import ProjectZipStreamManager from './ProjectZipStreamManager.mjs'
+import DocumentUpdaterHandler from '../DocumentUpdater/DocumentUpdaterHandler.js'
+import { prepareZipAttachment } from '../../infrastructure/Response.js'
+
 let ProjectDownloadsController
-const logger = require('@overleaf/logger')
-const Metrics = require('@overleaf/metrics')
-const ProjectGetter = require('../Project/ProjectGetter')
-const ProjectZipStreamManager = require('./ProjectZipStreamManager')
-const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
-const { prepareZipAttachment } = require('../../infrastructure/Response')
 
-module.exports = ProjectDownloadsController = {
+export default ProjectDownloadsController = {
   downloadProject(req, res, next) {
     const projectId = req.params.Project_id
     Metrics.inc('zip-downloads')

+ 7 - 7
services/web/app/src/Features/Downloads/ProjectZipStreamManager.js → services/web/app/src/Features/Downloads/ProjectZipStreamManager.mjs

@@ -1,12 +1,12 @@
+import archiver from 'archiver'
+import async from 'async'
+import logger from '@overleaf/logger'
+import ProjectEntityHandler from '../Project/ProjectEntityHandler.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import FileStoreHandler from '../FileStore/FileStoreHandler.js'
 let ProjectZipStreamManager
-const archiver = require('archiver')
-const async = require('async')
-const logger = require('@overleaf/logger')
-const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
-const ProjectGetter = require('../Project/ProjectGetter')
-const FileStoreHandler = require('../FileStore/FileStoreHandler')
 
-module.exports = ProjectZipStreamManager = {
+export default ProjectZipStreamManager = {
   createZipStreamForMultipleProjects(projectIds, callback) {
     // We'll build up a zip file that contains multiple zip files
     const archive = archiver('zip')

+ 7 - 7
services/web/app/src/Features/Editor/EditorRouter.js → services/web/app/src/Features/Editor/EditorRouter.mjs

@@ -1,9 +1,9 @@
-const EditorHttpController = require('./EditorHttpController')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const AuthorizationMiddleware = require('../Authorization/AuthorizationMiddleware')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
-const { validate, Joi } = require('../../infrastructure/Validation')
+import EditorHttpController from './EditorHttpController.js'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import AuthorizationMiddleware from '../Authorization/AuthorizationMiddleware.js'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
+import { validate, Joi } from '../../infrastructure/Validation.js'
 
 const rateLimiters = {
   addDocToProject: new RateLimiter('add-doc-to-project', {
@@ -17,7 +17,7 @@ const rateLimiters = {
   joinProject: new RateLimiter('join-project', { points: 45, duration: 60 }),
 }
 
-module.exports = {
+export default {
   apply(webRouter, privateApiRouter) {
     webRouter.post(
       '/project/:Project_id/doc',

+ 5 - 4
services/web/app/src/Features/Exports/ExportsController.js → services/web/app/src/Features/Exports/ExportsController.mjs

@@ -9,11 +9,12 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-const ExportsHandler = require('./ExportsHandler')
-const SessionManager = require('../Authentication/SessionManager')
-const logger = require('@overleaf/logger')
+import ExportsHandler from './ExportsHandler.mjs'
 
-module.exports = {
+import SessionManager from '../Authentication/SessionManager.js'
+import logger from '@overleaf/logger'
+
+export default {
   exportProject(req, res, next) {
     const { project_id: projectId, brand_variation_id: brandVariationId } =
       req.params

+ 12 - 13
services/web/app/src/Features/Exports/ExportsHandler.js → services/web/app/src/Features/Exports/ExportsHandler.mjs

@@ -11,21 +11,20 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import OError from '@overleaf/o-error'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import ProjectHistoryHandler from '../Project/ProjectHistoryHandler.js'
+import ProjectLocator from '../Project/ProjectLocator.js'
+import ProjectRootDocManager from '../Project/ProjectRootDocManager.js'
+import UserGetter from '../User/UserGetter.js'
+import logger from '@overleaf/logger'
+import settings from '@overleaf/settings'
+import async from 'async'
+import Request from 'request'
 let ExportsHandler
-const OError = require('@overleaf/o-error')
-const ProjectGetter = require('../Project/ProjectGetter')
-const ProjectHistoryHandler = require('../Project/ProjectHistoryHandler')
-const ProjectLocator = require('../Project/ProjectLocator')
-const ProjectRootDocManager = require('../Project/ProjectRootDocManager')
-const UserGetter = require('../User/UserGetter')
-const logger = require('@overleaf/logger')
-let settings = require('@overleaf/settings')
-const async = require('async')
-let request = require('request')
-request = request.defaults()
-settings = require('@overleaf/settings')
+const request = Request.defaults()
 
-module.exports = ExportsHandler = {
+export default ExportsHandler = {
   exportProject(exportParams, callback) {
     if (callback == null) {
       callback = function () {}

+ 6 - 7
services/web/app/src/Features/FileStore/FileStoreController.js → services/web/app/src/Features/FileStore/FileStoreController.mjs

@@ -1,11 +1,10 @@
-const logger = require('@overleaf/logger')
+import logger from '@overleaf/logger'
+import FileStoreHandler from './FileStoreHandler.js'
+import ProjectLocator from '../Project/ProjectLocator.js'
+import Errors from '../Errors/Errors.js'
+import { preparePlainTextResponse } from '../../infrastructure/Response.js'
 
-const FileStoreHandler = require('./FileStoreHandler')
-const ProjectLocator = require('../Project/ProjectLocator')
-const Errors = require('../Errors/Errors')
-const { preparePlainTextResponse } = require('../../infrastructure/Response')
-
-module.exports = {
+export default {
   getFile(req, res) {
     const projectId = req.params.Project_id
     const fileId = req.params.File_id

+ 9 - 8
services/web/app/src/Features/HealthCheck/HealthCheckController.js → services/web/app/src/Features/HealthCheck/HealthCheckController.mjs

@@ -1,14 +1,15 @@
-const RedisWrapper = require('../../infrastructure/RedisWrapper')
-const rclient = RedisWrapper.client('health_check')
-const settings = require('@overleaf/settings')
-const logger = require('@overleaf/logger')
-const UserGetter = require('../User/UserGetter')
-const {
+import RedisWrapper from '../../infrastructure/RedisWrapper.js'
+import settings from '@overleaf/settings'
+import logger from '@overleaf/logger'
+import UserGetter from '../User/UserGetter.js'
+import {
   SmokeTestFailure,
   runSmokeTests,
-} = require('./../../../../test/smoke/src/SmokeTests')
+} from './../../../../test/smoke/src/SmokeTests.js'
+
+const rclient = RedisWrapper.client('health_check')
 
-module.exports = {
+export default {
   check(req, res, next) {
     if (!settings.siteIsOpen || !settings.editorIsOpen) {
       // always return successful health checks when site is closed

+ 11 - 13
services/web/app/src/Features/History/HistoryRangesSupportMigration.js → services/web/app/src/Features/History/HistoryRangesSupportMigration.mjs

@@ -1,17 +1,15 @@
 // @ts-check
 
-const { callbackify } = require('util')
-const { ObjectId } = require('mongodb-legacy')
-const OError = require('@overleaf/o-error')
-const logger = require('@overleaf/logger')
-const HistoryManager = require('../History/HistoryManager')
-const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
-const DocstoreManager = require('../Docstore/DocstoreManager')
-const ProjectOptionsHandler = require('../Project/ProjectOptionsHandler')
-const {
-  db,
-  READ_PREFERENCE_SECONDARY,
-} = require('../../infrastructure/mongodb')
+import { callbackify } from 'util'
+import OError from '@overleaf/o-error'
+import logger from '@overleaf/logger'
+import HistoryManager from '../History/HistoryManager.js'
+import DocumentUpdaterHandler from '../DocumentUpdater/DocumentUpdaterHandler.js'
+import DocstoreManager from '../Docstore/DocstoreManager.js'
+import ProjectOptionsHandler from '../Project/ProjectOptionsHandler.js'
+import mongodb from '../../infrastructure/mongodb.js'
+
+const { db, ObjectId, READ_PREFERENCE_SECONDARY } = mongodb
 
 /**
  * Migrate projects based on a query.
@@ -267,7 +265,7 @@ async function hardResyncProject(projectId) {
   await HistoryManager.promises.resyncProject(projectId, { force: true })
 }
 
-module.exports = {
+export default {
   migrateProjects: callbackify(migrateProjects),
   migrateProject: callbackify(migrateProject),
   promises: { migrateProjects, migrateProject },

+ 2 - 2
services/web/app/src/Features/InactiveData/InactiveProjectController.js → services/web/app/src/Features/InactiveData/InactiveProjectController.mjs

@@ -9,9 +9,9 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-const InactiveProjectManager = require('./InactiveProjectManager')
+import InactiveProjectManager from './InactiveProjectManager.js'
 
-module.exports = {
+export default {
   deactivateOldProjects(req, res) {
     const numberOfProjectsToArchive = parseInt(
       req.body.numberOfProjectsToArchive,

+ 20 - 20
services/web/app/src/Features/LinkedFiles/LinkedFilesController.js → services/web/app/src/Features/LinkedFiles/LinkedFilesController.mjs

@@ -10,14 +10,12 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-let LinkedFilesController
-const SessionManager = require('../Authentication/SessionManager')
-const Settings = require('@overleaf/settings')
-const _ = require('lodash')
-const AnalyticsManager = require('../../../../app/src/Features/Analytics/AnalyticsManager')
-const LinkedFilesHandler = require('./LinkedFilesHandler')
-
-const {
+import SessionManager from '../Authentication/SessionManager.js'
+import Settings from '@overleaf/settings'
+import _ from 'lodash'
+import AnalyticsManager from '../../../../app/src/Features/Analytics/AnalyticsManager.js'
+import LinkedFilesHandler from './LinkedFilesHandler.js'
+import {
   CompileFailedError,
   UrlFetchFailedError,
   InvalidUrlError,
@@ -31,20 +29,22 @@ const {
   FeatureNotAvailableError,
   RemoteServiceError,
   FileCannotRefreshError,
-} = require('./LinkedFilesErrors')
-const {
+} from './LinkedFilesErrors.js'
+import {
   OutputFileFetchFailedError,
   FileTooLargeError,
   OError,
-} = require('../Errors/Errors')
-const Modules = require('../../infrastructure/Modules')
-const { plainTextResponse } = require('../../infrastructure/Response')
-const ReferencesHandler = require('../References/ReferencesHandler')
-const EditorRealTimeController = require('../Editor/EditorRealTimeController')
-const { expressify } = require('@overleaf/promise-utils')
-const ProjectOutputFileAgent = require('./ProjectOutputFileAgent')
-const ProjectFileAgent = require('./ProjectFileAgent')
-const UrlAgent = require('./UrlAgent')
+} from '../Errors/Errors.js'
+import Modules from '../../infrastructure/Modules.js'
+import { plainTextResponse } from '../../infrastructure/Response.js'
+import ReferencesHandler from '../References/ReferencesHandler.mjs'
+import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
+import { expressify } from '@overleaf/promise-utils'
+import ProjectOutputFileAgent from './ProjectOutputFileAgent.mjs'
+import ProjectFileAgent from './ProjectFileAgent.js'
+import UrlAgent from './UrlAgent.mjs'
+
+let LinkedFilesController
 
 async function createLinkedFile(req, res, next) {
   const { project_id: projectId } = req.params
@@ -146,7 +146,7 @@ async function refreshLinkedFile(req, res, next) {
   }
 }
 
-module.exports = LinkedFilesController = {
+export default LinkedFilesController = {
   Agents: null,
 
   async _cacheAgents() {

+ 7 - 7
services/web/app/src/Features/LinkedFiles/LinkedFilesRouter.js → services/web/app/src/Features/LinkedFiles/LinkedFilesRouter.mjs

@@ -1,9 +1,9 @@
-const AuthorizationMiddleware = require('../Authorization/AuthorizationMiddleware')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
-const LinkedFilesController = require('./LinkedFilesController')
-const { validate, Joi } = require('../../infrastructure/Validation')
+import AuthorizationMiddleware from '../Authorization/AuthorizationMiddleware.js'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
+import LinkedFilesController from './LinkedFilesController.mjs'
+import { validate, Joi } from '../../infrastructure/Validation.js'
 
 const rateLimiters = {
   createLinkedFile: new RateLimiter('create-linked-file', {
@@ -16,7 +16,7 @@ const rateLimiters = {
   }),
 }
 
-module.exports = {
+export default {
   apply(webRouter) {
     webRouter.post(
       '/project/:project_id/linked_file',

+ 11 - 11
services/web/app/src/Features/LinkedFiles/ProjectOutputFileAgent.js → services/web/app/src/Features/LinkedFiles/ProjectOutputFileAgent.mjs

@@ -1,16 +1,16 @@
-const AuthorizationManager = require('../Authorization/AuthorizationManager')
-const CompileManager = require('../Compile/CompileManager')
-const ClsiManager = require('../Compile/ClsiManager')
-const ProjectFileAgent = require('./ProjectFileAgent')
-const _ = require('lodash')
-const {
+import AuthorizationManager from '../Authorization/AuthorizationManager.js'
+import CompileManager from '../Compile/CompileManager.js'
+import ClsiManager from '../Compile/ClsiManager.js'
+import ProjectFileAgent from './ProjectFileAgent.js'
+import _ from 'lodash'
+import {
   CompileFailedError,
   BadDataError,
   AccessDeniedError,
-} = require('./LinkedFilesErrors')
-const { OutputFileFetchFailedError } = require('../Errors/Errors')
-const LinkedFilesHandler = require('./LinkedFilesHandler')
-const { promisify } = require('@overleaf/promise-utils')
+} from './LinkedFilesErrors.js'
+import { OutputFileFetchFailedError } from '../Errors/Errors.js'
+import LinkedFilesHandler from './LinkedFilesHandler.js'
+import { promisify } from '@overleaf/promise-utils'
 
 function _prepare(projectId, linkedFileData, userId, callback) {
   _checkAuth(projectId, linkedFileData, userId, (err, allowed) => {
@@ -226,7 +226,7 @@ function _compileAndGetFileStream(linkedFileData, userId, callback) {
   })
 }
 
-module.exports = {
+export default {
   createLinkedFile,
   refreshLinkedFile,
   promises: {

+ 9 - 9
services/web/app/src/Features/LinkedFiles/UrlAgent.js → services/web/app/src/Features/LinkedFiles/UrlAgent.mjs

@@ -1,11 +1,11 @@
-const logger = require('@overleaf/logger')
-const urlValidator = require('valid-url')
-const { InvalidUrlError, UrlFetchFailedError } = require('./LinkedFilesErrors')
-const LinkedFilesHandler = require('./LinkedFilesHandler')
-const UrlHelper = require('../Helpers/UrlHelper')
-const { fetchStream, RequestFailedError } = require('@overleaf/fetch-utils')
-const { callbackify } = require('@overleaf/promise-utils')
-const { FileTooLargeError } = require('../Errors/Errors')
+import logger from '@overleaf/logger'
+import urlValidator from 'valid-url'
+import { InvalidUrlError, UrlFetchFailedError } from './LinkedFilesErrors.js'
+import LinkedFilesHandler from './LinkedFilesHandler.js'
+import UrlHelper from '../Helpers/UrlHelper.js'
+import { fetchStream, RequestFailedError } from '@overleaf/fetch-utils'
+import { callbackify } from '@overleaf/promise-utils'
+import { FileTooLargeError } from '../Errors/Errors.js'
 
 async function createLinkedFile(
   projectId,
@@ -76,7 +76,7 @@ function _getUrl(projectId, data, currentUserId) {
   return url
 }
 
-module.exports = {
+export default {
   createLinkedFile: callbackify(createLinkedFile),
   refreshLinkedFile: callbackify(refreshLinkedFile),
   promises: { createLinkedFile, refreshLinkedFile },

+ 6 - 6
services/web/app/src/Features/Metadata/MetaController.js → services/web/app/src/Features/Metadata/MetaController.mjs

@@ -1,8 +1,8 @@
-const OError = require('@overleaf/o-error')
-const EditorRealTimeController = require('../Editor/EditorRealTimeController')
-const MetaHandler = require('./MetaHandler')
-const logger = require('@overleaf/logger')
-const { expressify } = require('@overleaf/promise-utils')
+import OError from '@overleaf/o-error'
+import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
+import MetaHandler from './MetaHandler.mjs'
+import logger from '@overleaf/logger'
+import { expressify } from '@overleaf/promise-utils'
 
 async function getMetadata(req, res) {
   const { project_id: projectId } = req.params
@@ -55,7 +55,7 @@ async function broadcastMetadataForDoc(req, res) {
   res.sendStatus(200) // 204?
 }
 
-module.exports = {
+export default {
   getMetadata: expressify(getMetadata),
   broadcastMetadataForDoc: expressify(broadcastMetadataForDoc),
 }

+ 5 - 5
services/web/app/src/Features/Metadata/MetaHandler.js → services/web/app/src/Features/Metadata/MetaHandler.mjs

@@ -1,7 +1,7 @@
-const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
-const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
-const packageMapping = require('./packageMapping')
-const { callbackify } = require('@overleaf/promise-utils')
+import ProjectEntityHandler from '../Project/ProjectEntityHandler.js'
+import DocumentUpdaterHandler from '../DocumentUpdater/DocumentUpdaterHandler.js'
+import packageMapping from './packageMapping.mjs'
+import { callbackify } from '@overleaf/promise-utils'
 
 /** @typedef {{
  *   labels: string[]
@@ -117,7 +117,7 @@ async function getMetaForDoc(projectId, docId) {
   return await extractMetaFromDoc(lines)
 }
 
-module.exports = {
+export default {
   promises: {
     getAllMetaForProject,
     getMetaForDoc,

+ 1 - 1
services/web/app/src/Features/Metadata/packageMapping.js → services/web/app/src/Features/Metadata/packageMapping.mjs

@@ -1,4 +1,4 @@
-module.exports = {
+export default {
   inputenc: [
     {
       caption: '\\inputencoding{}',

+ 4 - 4
services/web/app/src/Features/Notifications/NotificationsController.js → services/web/app/src/Features/Notifications/NotificationsController.mjs

@@ -1,8 +1,8 @@
-const NotificationsHandler = require('./NotificationsHandler')
-const SessionManager = require('../Authentication/SessionManager')
-const _ = require('lodash')
+import NotificationsHandler from './NotificationsHandler.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import _ from 'lodash'
 
-module.exports = {
+export default {
   getAllUnreadNotifications(req, res, next) {
     const userId = SessionManager.getLoggedInUserId(req.session)
     NotificationsHandler.getUserNotifications(

+ 11 - 11
services/web/app/src/Features/PasswordReset/PasswordResetController.js → services/web/app/src/Features/PasswordReset/PasswordResetController.mjs

@@ -1,13 +1,13 @@
-const PasswordResetHandler = require('./PasswordResetHandler')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const AuthenticationManager = require('../Authentication/AuthenticationManager')
-const SessionManager = require('../Authentication/SessionManager')
-const UserGetter = require('../User/UserGetter')
-const UserUpdater = require('../User/UserUpdater')
-const UserSessionsManager = require('../User/UserSessionsManager')
-const OError = require('@overleaf/o-error')
-const EmailsHelper = require('../Helpers/EmailHelper')
-const { expressify } = require('@overleaf/promise-utils')
+import PasswordResetHandler from './PasswordResetHandler.mjs'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import AuthenticationManager from '../Authentication/AuthenticationManager.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import UserGetter from '../User/UserGetter.js'
+import UserUpdater from '../User/UserUpdater.js'
+import UserSessionsManager from '../User/UserSessionsManager.js'
+import OError from '@overleaf/o-error'
+import EmailsHelper from '../Helpers/EmailHelper.js'
+import { expressify } from '@overleaf/promise-utils'
 
 async function setNewUserPassword(req, res, next) {
   let user
@@ -189,7 +189,7 @@ async function renderSetPasswordForm(req, res, next) {
   })
 }
 
-module.exports = {
+export default {
   renderRequestResetForm(req, res) {
     const errorQuery = req.query.error
     let error = null

+ 11 - 10
services/web/app/src/Features/PasswordReset/PasswordResetHandler.js → services/web/app/src/Features/PasswordReset/PasswordResetHandler.mjs

@@ -1,12 +1,13 @@
-const settings = require('@overleaf/settings')
-const UserAuditLogHandler = require('../User/UserAuditLogHandler')
-const UserGetter = require('../User/UserGetter')
-const OneTimeTokenHandler = require('../Security/OneTimeTokenHandler')
-const EmailHandler = require('../Email/EmailHandler')
-const AuthenticationManager = require('../Authentication/AuthenticationManager')
-const { callbackify, promisify } = require('util')
-const { assertUserPermissions } =
-  require('../Authorization/PermissionsManager').promises
+import settings from '@overleaf/settings'
+import UserAuditLogHandler from '../User/UserAuditLogHandler.js'
+import UserGetter from '../User/UserGetter.js'
+import OneTimeTokenHandler from '../Security/OneTimeTokenHandler.js'
+import EmailHandler from '../Email/EmailHandler.js'
+import AuthenticationManager from '../Authentication/AuthenticationManager.js'
+import { callbackify, promisify } from 'util'
+import PermissionsManager from '../Authorization/PermissionsManager.js'
+
+const assertUserPermissions = PermissionsManager.promises.assertUserPermissions
 
 const AUDIT_LOG_TOKEN_PREFIX_LENGTH = 10
 
@@ -138,4 +139,4 @@ PasswordResetHandler.promises = {
   setNewUserPassword,
 }
 
-module.exports = PasswordResetHandler
+export default PasswordResetHandler

+ 7 - 7
services/web/app/src/Features/PasswordReset/PasswordResetRouter.js → services/web/app/src/Features/PasswordReset/PasswordResetRouter.mjs

@@ -1,16 +1,16 @@
-const PasswordResetController = require('./PasswordResetController')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const CaptchaMiddleware = require('../../Features/Captcha/CaptchaMiddleware')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
-const { Joi, validate } = require('../../infrastructure/Validation')
+import PasswordResetController from './PasswordResetController.mjs'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import CaptchaMiddleware from '../../Features/Captcha/CaptchaMiddleware.js'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
+import { Joi, validate } from '../../infrastructure/Validation.js'
 
 const rateLimiter = new RateLimiter('password_reset_rate_limit', {
   points: 6,
   duration: 60,
 })
 
-module.exports = {
+export default {
   apply(webRouter) {
     const rateLimit = RateLimiterMiddleware.rateLimit(rateLimiter, {
       ipOnly: true,

+ 2 - 2
services/web/app/src/Features/Project/DocLinesComparitor.js → services/web/app/src/Features/Project/DocLinesComparitor.mjs

@@ -1,8 +1,8 @@
 // TODO: This file was created by bulk-decaffeinate.
 // Sanity-check the conversion and remove this comment.
-const _ = require('lodash')
+import _ from 'lodash'
 
-module.exports = {
+export default {
   areSame(lines1, lines2) {
     if (!Array.isArray(lines1) || !Array.isArray(lines2)) {
       return false

+ 4 - 3
services/web/app/src/Features/Project/ProjectApiController.js → services/web/app/src/Features/Project/ProjectApiController.mjs

@@ -10,10 +10,11 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-const ProjectDetailsHandler = require('./ProjectDetailsHandler')
-const logger = require('@overleaf/logger')
+import ProjectDetailsHandler from './ProjectDetailsHandler.js'
 
-module.exports = {
+import logger from '@overleaf/logger'
+
+export default {
   getProjectDetails(req, res, next) {
     const { project_id: projectId } = req.params
     return ProjectDetailsHandler.getDetails(

+ 30 - 29
services/web/app/src/Features/Project/ProjectListController.js → services/web/app/src/Features/Project/ProjectListController.mjs

@@ -1,32 +1,33 @@
 // ts-check
-const _ = require('lodash')
-const Metrics = require('@overleaf/metrics')
-const Settings = require('@overleaf/settings')
-const ProjectHelper = require('./ProjectHelper')
-const ProjectGetter = require('./ProjectGetter')
-const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
-const SessionManager = require('../Authentication/SessionManager')
-const Sources = require('../Authorization/Sources')
-const UserGetter = require('../User/UserGetter')
-const SurveyHandler = require('../Survey/SurveyHandler')
-const TagsHandler = require('../Tags/TagsHandler')
-const { expressify } = require('@overleaf/promise-utils')
-const logger = require('@overleaf/logger')
-const Features = require('../../infrastructure/Features')
-const SubscriptionViewModelBuilder = require('../Subscription/SubscriptionViewModelBuilder')
-const NotificationsHandler = require('../Notifications/NotificationsHandler')
-const Modules = require('../../infrastructure/Modules')
-const { OError, V1ConnectionError } = require('../Errors/Errors')
-const { User } = require('../../models/User')
-const UserPrimaryEmailCheckHandler = require('../User/UserPrimaryEmailCheckHandler')
-const UserController = require('../User/UserController')
-const LimitationsManager = require('../Subscription/LimitationsManager')
-const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
-const GeoIpLookup = require('../../infrastructure/GeoIpLookup')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
-const SplitTestSessionHandler = require('../SplitTests/SplitTestSessionHandler')
-const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
-const TutorialHandler = require('../Tutorial/TutorialHandler')
+import _ from 'lodash'
+
+import Metrics from '@overleaf/metrics'
+import Settings from '@overleaf/settings'
+import ProjectHelper from './ProjectHelper.js'
+import ProjectGetter from './ProjectGetter.js'
+import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import Sources from '../Authorization/Sources.js'
+import UserGetter from '../User/UserGetter.js'
+import SurveyHandler from '../Survey/SurveyHandler.mjs'
+import TagsHandler from '../Tags/TagsHandler.js'
+import { expressify } from '@overleaf/promise-utils'
+import logger from '@overleaf/logger'
+import Features from '../../infrastructure/Features.js'
+import SubscriptionViewModelBuilder from '../Subscription/SubscriptionViewModelBuilder.js'
+import NotificationsHandler from '../Notifications/NotificationsHandler.js'
+import Modules from '../../infrastructure/Modules.js'
+import { OError, V1ConnectionError } from '../Errors/Errors.js'
+import { User } from '../../models/User.js'
+import UserPrimaryEmailCheckHandler from '../User/UserPrimaryEmailCheckHandler.js'
+import UserController from '../User/UserController.js'
+import LimitationsManager from '../Subscription/LimitationsManager.js'
+import NotificationsBuilder from '../Notifications/NotificationsBuilder.js'
+import GeoIpLookup from '../../infrastructure/GeoIpLookup.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
+import SplitTestSessionHandler from '../SplitTests/SplitTestSessionHandler.js'
+import SubscriptionLocator from '../Subscription/SubscriptionLocator.js'
+import TutorialHandler from '../Tutorial/TutorialHandler.js'
 
 /**
  * @import { GetProjectsRequest, GetProjectsResponse, AllUsersProjects, MongoProject } from "./types"
@@ -763,7 +764,7 @@ function _hasActiveFilter(filters) {
   )
 }
 
-module.exports = {
+export default {
   projectListPage: expressify(projectListPage),
   getProjectsJson: expressify(getProjectsJson),
 }

+ 1 - 1
services/web/app/src/Features/Referal/ReferalConnect.js → services/web/app/src/Features/Referal/ReferalConnect.mjs

@@ -1,4 +1,4 @@
-module.exports = {
+export default {
   use(req, res, next) {
     if (req.query != null) {
       if (req.query.referal != null) {

+ 3 - 3
services/web/app/src/Features/Referal/ReferalController.js → services/web/app/src/Features/Referal/ReferalController.mjs

@@ -1,7 +1,7 @@
-const ReferalHandler = require('./ReferalHandler')
-const SessionManager = require('../Authentication/SessionManager')
+import ReferalHandler from './ReferalHandler.mjs'
+import SessionManager from '../Authentication/SessionManager.js'
 
-module.exports = {
+export default {
   bonus(req, res, next) {
     const userId = SessionManager.getLoggedInUserId(req.session)
     ReferalHandler.getReferedUsers(userId, (err, { referedUserCount }) => {

+ 3 - 3
services/web/app/src/Features/Referal/ReferalHandler.js → services/web/app/src/Features/Referal/ReferalHandler.mjs

@@ -1,5 +1,5 @@
-const { callbackify } = require('@overleaf/promise-utils')
-const { User } = require('../../models/User')
+import { callbackify } from '@overleaf/promise-utils'
+import { User } from '../../models/User.js'
 
 async function getReferedUsers(userId) {
   const projection = { refered_users: 1, refered_user_count: 1 }
@@ -9,7 +9,7 @@ async function getReferedUsers(userId) {
   return { referedUsers, referedUserCount }
 }
 
-module.exports = {
+export default {
   getReferedUsers: callbackify(getReferedUsers),
   promises: {
     getReferedUsers,

+ 5 - 6
services/web/app/src/Features/References/ReferencesController.js → services/web/app/src/Features/References/ReferencesController.mjs

@@ -10,14 +10,13 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import ReferencesHandler from './ReferencesHandler.mjs'
+import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
+import { OError } from '../Errors/Errors.js'
+
 let ReferencesController
-const logger = require('@overleaf/logger')
-const ReferencesHandler = require('./ReferencesHandler')
-const settings = require('@overleaf/settings')
-const EditorRealTimeController = require('../Editor/EditorRealTimeController')
-const { OError } = require('../Errors/Errors')
 
-module.exports = ReferencesController = {
+export default ReferencesController = {
   indexAll(req, res, next) {
     const projectId = req.params.Project_id
     const { shouldBroadcast } = req.body

+ 14 - 13
services/web/app/src/Features/References/ReferencesHandler.js → services/web/app/src/Features/References/ReferencesHandler.mjs

@@ -12,25 +12,26 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import OError from '@overleaf/o-error'
+import logger from '@overleaf/logger'
+import request from 'request'
+import settings from '@overleaf/settings'
+import Features from '../../infrastructure/Features.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import UserGetter from '../User/UserGetter.js'
+import DocumentUpdaterHandler from '../DocumentUpdater/DocumentUpdaterHandler.js'
+import _ from 'lodash'
+import Async from 'async'
+import Errors from '../Errors/Errors.js'
+import { promisify } from '@overleaf/promise-utils'
+
 let ReferencesHandler
-const OError = require('@overleaf/o-error')
-const logger = require('@overleaf/logger')
-const request = require('request')
-const settings = require('@overleaf/settings')
-const Features = require('../../infrastructure/Features')
-const ProjectGetter = require('../Project/ProjectGetter')
-const UserGetter = require('../User/UserGetter')
-const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
-const _ = require('lodash')
-const Async = require('async')
-const Errors = require('../Errors/Errors')
-const { promisify } = require('@overleaf/promise-utils')
 
 if (!Features.hasFeature('references')) {
   logger.debug('references search not enabled')
 }
 
-module.exports = ReferencesHandler = {
+export default ReferencesHandler = {
   _buildDocUrl(projectId, docId) {
     return `${settings.apis.docstore.url}/project/${projectId}/doc/${docId}/raw`
   },

+ 6 - 6
services/web/app/src/Features/Spelling/SpellingController.js → services/web/app/src/Features/Spelling/SpellingController.mjs

@@ -1,15 +1,15 @@
-const request = require('request')
-const Settings = require('@overleaf/settings')
-const logger = require('@overleaf/logger')
-const SessionManager = require('../Authentication/SessionManager')
-const LearnedWordsManager = require('./LearnedWordsManager')
+import request from 'request'
+import Settings from '@overleaf/settings'
+import logger from '@overleaf/logger'
+import SessionManager from '../Authentication/SessionManager.js'
+import LearnedWordsManager from './LearnedWordsManager.js'
 
 const TEN_SECONDS = 1000 * 10
 
 const languageCodeIsSupported = code =>
   Settings.languages.some(lang => lang.code === code && lang.server !== false)
 
-module.exports = {
+export default {
   learn(req, res, next) {
     const { word } = req.body
     const userId = SessionManager.getLoggedInUserId(req.session)

+ 11 - 12
services/web/app/src/Features/StaticPages/HomeController.js → services/web/app/src/Features/StaticPages/HomeController.mjs

@@ -1,15 +1,14 @@
-const Features = require('../../infrastructure/Features')
-const AnalyticsManager = require('../Analytics/AnalyticsManager')
+import Features from '../../infrastructure/Features.js'
+import AnalyticsManager from '../Analytics/AnalyticsManager.js'
+import Path from 'path'
+import fs from 'fs'
+import ErrorController from '../Errors/ErrorController.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import { expressify } from '@overleaf/promise-utils'
+import logger from '@overleaf/logger'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
 
-const Path = require('path')
-const fs = require('fs')
-
-const ErrorController = require('../Errors/ErrorController')
-const SessionManager = require('../Authentication/SessionManager')
-
-const { expressify } = require('@overleaf/promise-utils')
-const logger = require('@overleaf/logger')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
+const __dirname = new URL('.', import.meta.url).pathname
 
 const homepageExists = fs.existsSync(
   Path.join(
@@ -67,7 +66,7 @@ function externalPage(page, title) {
   return expressify(middleware)
 }
 
-module.exports = {
+export default {
   index: expressify(index),
   home: expressify(home),
   externalPage,

+ 3 - 2
services/web/app/src/Features/StaticPages/StaticPageHelpers.js → services/web/app/src/Features/StaticPages/StaticPageHelpers.mjs

@@ -8,6 +8,8 @@
  * DS102: Remove unnecessary code created because of implicit returns
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import _ from 'lodash'
+
 const extensionsToProxy = [
   '.png',
   '.xml',
@@ -18,9 +20,8 @@ const extensionsToProxy = [
   '.gif',
   '.jpg',
 ]
-const _ = require('lodash')
 
-module.exports = {
+export default {
   shouldProxy(url) {
     const shouldProxy = _.find(
       extensionsToProxy,

+ 4 - 3
services/web/app/src/Features/StaticPages/StaticPagesRouter.js → services/web/app/src/Features/StaticPages/StaticPagesRouter.mjs

@@ -8,10 +8,11 @@
  * DS102: Remove unnecessary code created because of implicit returns
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
-const HomeController = require('./HomeController')
-const UniversityController = require('./UniversityController')
+import HomeController from './HomeController.mjs'
 
-module.exports = {
+import UniversityController from './UniversityController.mjs'
+
+export default {
   apply(webRouter) {
     webRouter.get('/', HomeController.index)
     webRouter.get('/home', HomeController.home)

+ 1 - 4
services/web/app/src/Features/StaticPages/UniversityController.js → services/web/app/src/Features/StaticPages/UniversityController.mjs

@@ -10,11 +10,8 @@
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
 let UniversityController
-const settings = require('@overleaf/settings')
-const logger = require('@overleaf/logger')
-const Settings = require('@overleaf/settings')
 
-module.exports = UniversityController = {
+export default UniversityController = {
   getPage(req, res, next) {
     const url =
       req.url != null ? req.url.toLowerCase().replace('.html', '') : undefined

+ 10 - 9
services/web/app/src/Features/Subscription/SubscriptionGroupController.js → services/web/app/src/Features/Subscription/SubscriptionGroupController.mjs

@@ -1,12 +1,13 @@
 // ts-check
-const SubscriptionGroupHandler = require('./SubscriptionGroupHandler')
-const OError = require('@overleaf/o-error')
-const logger = require('@overleaf/logger')
-const SubscriptionLocator = require('./SubscriptionLocator')
-const SessionManager = require('../Authentication/SessionManager')
-const UserAuditLogHandler = require('../User/UserAuditLogHandler')
-const { expressify } = require('@overleaf/promise-utils')
-const Modules = require('../../infrastructure/Modules')
+import SubscriptionGroupHandler from './SubscriptionGroupHandler.js'
+
+import OError from '@overleaf/o-error'
+import logger from '@overleaf/logger'
+import SubscriptionLocator from './SubscriptionLocator.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import UserAuditLogHandler from '../User/UserAuditLogHandler.js'
+import { expressify } from '@overleaf/promise-utils'
+import Modules from '../../infrastructure/Modules.js'
 
 /**
  * @import { Subscription } from "../../../../types/subscription/dashboard/subscription"
@@ -110,7 +111,7 @@ async function _removeUserFromGroup(
   res.sendStatus(200)
 }
 
-module.exports = {
+export default {
   removeUserFromGroup: expressify(removeUserFromGroup),
   removeSelfFromGroup: expressify(removeSelfFromGroup),
 }

+ 10 - 10
services/web/app/src/Features/Subscription/SubscriptionRouter.js → services/web/app/src/Features/Subscription/SubscriptionRouter.mjs

@@ -1,12 +1,12 @@
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const PermissionsController = require('../Authorization/PermissionsController')
-const SubscriptionController = require('./SubscriptionController')
-const SubscriptionGroupController = require('./SubscriptionGroupController')
-const TeamInvitesController = require('./TeamInvitesController')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
-const Settings = require('@overleaf/settings')
-const { Joi, validate } = require('../../infrastructure/Validation')
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import PermissionsController from '../Authorization/PermissionsController.js'
+import SubscriptionController from './SubscriptionController.js'
+import SubscriptionGroupController from './SubscriptionGroupController.mjs'
+import TeamInvitesController from './TeamInvitesController.mjs'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
+import Settings from '@overleaf/settings'
+import { Joi, validate } from '../../infrastructure/Validation.js'
 
 const teamInviteRateLimiter = new RateLimiter('team-invite', {
   points: 10,
@@ -18,7 +18,7 @@ const subscriptionRateLimiter = new RateLimiter('subscription', {
   duration: 60,
 })
 
-module.exports = {
+export default {
   apply(webRouter, privateApiRouter, publicApiRouter) {
     if (!Settings.enableSubscriptions) {
       return

+ 18 - 18
services/web/app/src/Features/Subscription/TeamInvitesController.js → services/web/app/src/Features/Subscription/TeamInvitesController.mjs

@@ -1,20 +1,20 @@
-const settings = require('@overleaf/settings')
-const logger = require('@overleaf/logger')
-const OError = require('@overleaf/o-error')
-const TeamInvitesHandler = require('./TeamInvitesHandler')
-const SessionManager = require('../Authentication/SessionManager')
-const SubscriptionLocator = require('./SubscriptionLocator')
-const ErrorController = require('../Errors/ErrorController')
-const EmailHelper = require('../Helpers/EmailHelper')
-const UserGetter = require('../User/UserGetter')
-const { expressify } = require('@overleaf/promise-utils')
-const HttpErrorHandler = require('../Errors/HttpErrorHandler')
-const PermissionsManager = require('../Authorization/PermissionsManager')
-const EmailHandler = require('../Email/EmailHandler')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const Modules = require('../../infrastructure/Modules')
-const UserAuditLogHandler = require('../User/UserAuditLogHandler')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
+import settings from '@overleaf/settings'
+import logger from '@overleaf/logger'
+import OError from '@overleaf/o-error'
+import TeamInvitesHandler from './TeamInvitesHandler.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import SubscriptionLocator from './SubscriptionLocator.js'
+import ErrorController from '../Errors/ErrorController.js'
+import EmailHelper from '../Helpers/EmailHelper.js'
+import UserGetter from '../User/UserGetter.js'
+import { expressify } from '@overleaf/promise-utils'
+import HttpErrorHandler from '../Errors/HttpErrorHandler.js'
+import PermissionsManager from '../Authorization/PermissionsManager.js'
+import EmailHandler from '../Email/EmailHandler.js'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import Modules from '../../infrastructure/Modules.js'
+import UserAuditLogHandler from '../User/UserAuditLogHandler.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
 
 const rateLimiters = {
   resendGroupInvite: new RateLimiter('resend-group-invite', {
@@ -306,7 +306,7 @@ async function resendInvite(req, res, next) {
   return res.status(200).json({ success: true })
 }
 
-module.exports = {
+export default {
   createInvite: expressify(createInvite),
   viewInvite: expressify(viewInvite),
   viewInvites: expressify(viewInvites),

+ 4 - 4
services/web/app/src/Features/Survey/SurveyCache.js → services/web/app/src/Features/Survey/SurveyCache.mjs

@@ -1,6 +1,6 @@
-const SurveyManager = require('./SurveyManager')
-const { Survey } = require('../../models/Survey')
-const { CacheLoader } = require('cache-flow')
+import SurveyManager from './SurveyManager.js'
+import { Survey } from '../../models/Survey.js'
+import { CacheLoader } from 'cache-flow'
 
 class SurveyCache extends CacheLoader {
   constructor() {
@@ -22,4 +22,4 @@ class SurveyCache extends CacheLoader {
   }
 }
 
-module.exports = new SurveyCache()
+export default new SurveyCache()

+ 6 - 5
services/web/app/src/Features/Survey/SurveyHandler.js → services/web/app/src/Features/Survey/SurveyHandler.mjs

@@ -1,8 +1,9 @@
 // ts-check
-const crypto = require('crypto')
-const SurveyCache = require('./SurveyCache')
-const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
-const { callbackify } = require('@overleaf/promise-utils')
+import crypto from 'crypto'
+
+import SurveyCache from './SurveyCache.mjs'
+import SubscriptionLocator from '../Subscription/SubscriptionLocator.js'
+import { callbackify } from '@overleaf/promise-utils'
 
 /**
  * @import { Survey } from '../../../../types/project/dashboard/survey'
@@ -55,7 +56,7 @@ function _userInRolloutPercentile(userId, surveyName, rolloutPercentage) {
   return userPercentile < rolloutPercentage
 }
 
-module.exports = {
+export default {
   getSurvey: callbackify(getSurvey),
   promises: {
     getSurvey,

+ 5 - 5
services/web/app/src/Features/Tags/TagsController.js → services/web/app/src/Features/Tags/TagsController.mjs

@@ -1,7 +1,7 @@
-const TagsHandler = require('./TagsHandler')
-const SessionManager = require('../Authentication/SessionManager')
-const Errors = require('../Errors/Errors')
-const { expressify } = require('@overleaf/promise-utils')
+import TagsHandler from './TagsHandler.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import Errors from '../Errors/Errors.js'
+import { expressify } from '@overleaf/promise-utils'
 
 async function _getTags(userId, _req, res) {
   if (!userId) {
@@ -88,7 +88,7 @@ async function editTag(req, res) {
   res.status(204).end()
 }
 
-module.exports = {
+export default {
   apiGetAllTags: expressify(apiGetAllTags),
   getAllTags: expressify(getAllTags),
   createTag: expressify(createTag),

+ 14 - 14
services/web/app/src/Features/ThirdPartyDataStore/TpdsController.js → services/web/app/src/Features/ThirdPartyDataStore/TpdsController.mjs

@@ -1,16 +1,16 @@
-const { expressify } = require('@overleaf/promise-utils')
-const TpdsUpdateHandler = require('./TpdsUpdateHandler')
-const UpdateMerger = require('./UpdateMerger')
-const Errors = require('../Errors/Errors')
-const logger = require('@overleaf/logger')
-const Path = require('path')
-const metrics = require('@overleaf/metrics')
-const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
-const SessionManager = require('../Authentication/SessionManager')
-const ProjectCreationHandler = require('../Project/ProjectCreationHandler')
-const ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
-const HttpErrorHandler = require('../Errors/HttpErrorHandler')
-const TpdsQueueManager = require('./TpdsQueueManager')
+import { expressify } from '@overleaf/promise-utils'
+import TpdsUpdateHandler from './TpdsUpdateHandler.mjs'
+import UpdateMerger from './UpdateMerger.js'
+import Errors from '../Errors/Errors.js'
+import logger from '@overleaf/logger'
+import Path from 'path'
+import metrics from '@overleaf/metrics'
+import NotificationsBuilder from '../Notifications/NotificationsBuilder.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import ProjectCreationHandler from '../Project/ProjectCreationHandler.js'
+import ProjectDetailsHandler from '../Project/ProjectDetailsHandler.js'
+import HttpErrorHandler from '../Errors/HttpErrorHandler.js'
+import TpdsQueueManager from './TpdsQueueManager.mjs'
 
 async function createProject(req, res) {
   const { user_id: userId } = req.params
@@ -197,7 +197,7 @@ function splitPath(projectId, path) {
   return { filePath, projectName }
 }
 
-module.exports = {
+export default {
   createProject: expressify(createProject),
   mergeUpdate: expressify(mergeUpdate),
   deleteUpdate: expressify(deleteUpdate),

+ 4 - 4
services/web/app/src/Features/ThirdPartyDataStore/TpdsQueueManager.js → services/web/app/src/Features/ThirdPartyDataStore/TpdsQueueManager.mjs

@@ -1,6 +1,6 @@
-const Settings = require('@overleaf/settings')
-const OError = require('@overleaf/o-error')
-const { fetchJson } = require('@overleaf/fetch-utils')
+import Settings from '@overleaf/settings'
+import OError from '@overleaf/o-error'
+import { fetchJson } from '@overleaf/fetch-utils'
 
 async function getQueues(userId) {
   try {
@@ -10,7 +10,7 @@ async function getQueues(userId) {
   }
 }
 
-module.exports = {
+export default {
   promises: {
     getQueues,
   },

+ 14 - 14
services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.js → services/web/app/src/Features/ThirdPartyDataStore/TpdsUpdateHandler.mjs

@@ -1,16 +1,16 @@
-const { callbackify } = require('util')
-const UpdateMerger = require('./UpdateMerger')
-const logger = require('@overleaf/logger')
-const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
-const ProjectCreationHandler = require('../Project/ProjectCreationHandler')
-const ProjectDeleter = require('../Project/ProjectDeleter')
-const ProjectGetter = require('../Project/ProjectGetter')
-const ProjectHelper = require('../Project/ProjectHelper')
-const ProjectRootDocManager = require('../Project/ProjectRootDocManager')
-const FileTypeManager = require('../Uploads/FileTypeManager')
-const CooldownManager = require('../Cooldown/CooldownManager')
-const Errors = require('../Errors/Errors')
-const Modules = require('../../infrastructure/Modules')
+import { callbackify } from 'util'
+import UpdateMerger from './UpdateMerger.js'
+import logger from '@overleaf/logger'
+import NotificationsBuilder from '../Notifications/NotificationsBuilder.js'
+import ProjectCreationHandler from '../Project/ProjectCreationHandler.js'
+import ProjectDeleter from '../Project/ProjectDeleter.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import ProjectHelper from '../Project/ProjectHelper.js'
+import ProjectRootDocManager from '../Project/ProjectRootDocManager.js'
+import FileTypeManager from '../Uploads/FileTypeManager.js'
+import CooldownManager from '../Cooldown/CooldownManager.js'
+import Errors from '../Errors/Errors.js'
+import Modules from '../../infrastructure/Modules.js'
 
 async function newUpdate(
   userId,
@@ -189,7 +189,7 @@ async function createFolder(userId, projectId, projectName, path) {
   }
 }
 
-module.exports = {
+export default {
   newUpdate: callbackify(newUpdate),
   deleteUpdate: callbackify(deleteUpdate),
   createFolder: callbackify(createFolder),

+ 25 - 28
services/web/app/src/Features/TokenAccess/TokenAccessController.js → services/web/app/src/Features/TokenAccess/TokenAccessController.mjs

@@ -1,29 +1,26 @@
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const SessionManager = require('../Authentication/SessionManager')
-const TokenAccessHandler = require('./TokenAccessHandler')
-const Errors = require('../Errors/Errors')
-const logger = require('@overleaf/logger')
-const settings = require('@overleaf/settings')
-const OError = require('@overleaf/o-error')
-const { expressify } = require('@overleaf/promise-utils')
-const AuthorizationManager = require('../Authorization/AuthorizationManager')
-const PrivilegeLevels = require('../Authorization/PrivilegeLevels')
-const ProjectAuditLogHandler = require('../Project/ProjectAuditLogHandler')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
-const CollaboratorsInviteHandler = require('../Collaborators/CollaboratorsInviteHandler')
-const CollaboratorsHandler = require('../Collaborators/CollaboratorsHandler')
-const EditorRealTimeController = require('../Editor/EditorRealTimeController')
-const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
-const ProjectGetter = require('../Project/ProjectGetter')
-const AsyncFormHelper = require('../Helpers/AsyncFormHelper')
-const AnalyticsManager = require('../Analytics/AnalyticsManager')
-const {
-  canRedirectToAdminDomain,
-} = require('../Helpers/AdminAuthorizationHelper')
-const { getSafeAdminDomainRedirect } = require('../Helpers/UrlHelper')
-const UserGetter = require('../User/UserGetter')
-const Settings = require('@overleaf/settings')
-const LimitationsManager = require('../Subscription/LimitationsManager')
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import TokenAccessHandler from './TokenAccessHandler.js'
+import Errors from '../Errors/Errors.js'
+import logger from '@overleaf/logger'
+import OError from '@overleaf/o-error'
+import { expressify } from '@overleaf/promise-utils'
+import AuthorizationManager from '../Authorization/AuthorizationManager.js'
+import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
+import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
+import CollaboratorsInviteHandler from '../Collaborators/CollaboratorsInviteHandler.mjs'
+import CollaboratorsHandler from '../Collaborators/CollaboratorsHandler.js'
+import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
+import CollaboratorsGetter from '../Collaborators/CollaboratorsGetter.js'
+import ProjectGetter from '../Project/ProjectGetter.js'
+import AsyncFormHelper from '../Helpers/AsyncFormHelper.js'
+import AnalyticsManager from '../Analytics/AnalyticsManager.js'
+import { canRedirectToAdminDomain } from '../Helpers/AdminAuthorizationHelper.js'
+import { getSafeAdminDomainRedirect } from '../Helpers/UrlHelper.js'
+import UserGetter from '../User/UserGetter.js'
+import Settings from '@overleaf/settings'
+import LimitationsManager from '../Subscription/LimitationsManager.js'
 
 const orderedPrivilegeLevels = [
   PrivilegeLevels.NONE,
@@ -167,7 +164,7 @@ async function checkAndGetProjectOrResponseAction(
     token
   )
   if (!project) {
-    if (settings.overleaf) {
+    if (Settings.overleaf) {
       const v1ImportData = await _handleV1Project(token, userId)
       return [
         null,
@@ -645,7 +642,7 @@ async function moveReadWriteToReadOnly(req, res, next) {
   res.sendStatus(204)
 }
 
-module.exports = {
+export default {
   READ_ONLY_TOKEN_PATTERN: TokenAccessHandler.READ_ONLY_TOKEN_PATTERN,
   READ_AND_WRITE_TOKEN_PATTERN: TokenAccessHandler.READ_AND_WRITE_TOKEN_PATTERN,
 

+ 4 - 4
services/web/app/src/Features/TokenAccess/TokenAccessRouter.js → services/web/app/src/Features/TokenAccess/TokenAccessRouter.mjs

@@ -1,8 +1,8 @@
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const AuthorizationMiddleware = require('../Authorization/AuthorizationMiddleware')
-const TokenAccessController = require('./TokenAccessController')
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import AuthorizationMiddleware from '../Authorization/AuthorizationMiddleware.js'
+import TokenAccessController from './TokenAccessController.mjs'
 
-module.exports = {
+export default {
   apply(webRouter) {
     webRouter.get(
       `/project/:Project_id/sharing-updates`,

+ 4 - 4
services/web/app/src/Features/Tutorial/TutorialController.js → services/web/app/src/Features/Tutorial/TutorialController.mjs

@@ -1,6 +1,6 @@
-const SessionManager = require('../Authentication/SessionManager')
-const TutorialHandler = require('./TutorialHandler')
-const { expressify } = require('@overleaf/promise-utils')
+import SessionManager from '../Authentication/SessionManager.js'
+import TutorialHandler from './TutorialHandler.js'
+import { expressify } from '@overleaf/promise-utils'
 
 const VALID_KEYS = [
   'react-history-buttons-tutorial',
@@ -46,7 +46,7 @@ async function postponeTutorial(req, res, next) {
   res.sendStatus(204)
 }
 
-module.exports = {
+export default {
   completeTutorial: expressify(completeTutorial),
   postponeTutorial: expressify(postponeTutorial),
 }

+ 18 - 16
services/web/app/src/Features/Uploads/ProjectUploadController.js → services/web/app/src/Features/Uploads/ProjectUploadController.mjs

@@ -1,18 +1,20 @@
-const logger = require('@overleaf/logger')
-const metrics = require('@overleaf/metrics')
-const fs = require('fs')
-const Path = require('path')
-const FileSystemImportManager = require('./FileSystemImportManager')
-const ProjectUploadManager = require('./ProjectUploadManager')
-const SessionManager = require('../Authentication/SessionManager')
-const EditorController = require('../Editor/EditorController')
-const ProjectLocator = require('../Project/ProjectLocator')
-const Settings = require('@overleaf/settings')
-const { InvalidZipFileError } = require('./ArchiveErrors')
-const multer = require('multer')
-const { defaultsDeep } = require('lodash')
-const { expressify } = require('@overleaf/promise-utils')
-const { DuplicateNameError } = require('../Errors/Errors')
+import logger from '@overleaf/logger'
+import metrics from '@overleaf/metrics'
+import fs from 'fs'
+import Path from 'path'
+import FileSystemImportManager from './FileSystemImportManager.js'
+import ProjectUploadManager from './ProjectUploadManager.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import EditorController from '../Editor/EditorController.js'
+import ProjectLocator from '../Project/ProjectLocator.js'
+import Settings from '@overleaf/settings'
+import { InvalidZipFileError } from './ArchiveErrors.js'
+import multer from 'multer'
+import lodash from 'lodash'
+import { expressify } from '@overleaf/promise-utils'
+import { DuplicateNameError } from '../Errors/Errors.js'
+
+const defaultsDeep = lodash.defaultsDeep
 
 const upload = multer(
   defaultsDeep(
@@ -164,7 +166,7 @@ function multerMiddleware(req, res, next) {
   })
 }
 
-module.exports = {
+export default {
   uploadProject,
   uploadFile: expressify(uploadFile),
   multerMiddleware,

+ 7 - 7
services/web/app/src/Features/Uploads/UploadsRouter.js → services/web/app/src/Features/Uploads/UploadsRouter.mjs

@@ -1,9 +1,9 @@
-const AuthorizationMiddleware = require('../Authorization/AuthorizationMiddleware')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const ProjectUploadController = require('./ProjectUploadController')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
-const Settings = require('@overleaf/settings')
+import AuthorizationMiddleware from '../Authorization/AuthorizationMiddleware.js'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import ProjectUploadController from './ProjectUploadController.mjs'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
+import Settings from '@overleaf/settings'
 
 const rateLimiters = {
   projectUpload: new RateLimiter('project-upload', {
@@ -16,7 +16,7 @@ const rateLimiters = {
   }),
 }
 
-module.exports = {
+export default {
   apply(webRouter) {
     webRouter.post(
       '/project/new/upload',

+ 15 - 15
services/web/app/src/Features/User/UserPagesController.js → services/web/app/src/Features/User/UserPagesController.mjs

@@ -1,17 +1,17 @@
-const UserGetter = require('./UserGetter')
-const OError = require('@overleaf/o-error')
-const UserSessionsManager = require('./UserSessionsManager')
-const logger = require('@overleaf/logger')
-const Settings = require('@overleaf/settings')
-const AuthenticationController = require('../Authentication/AuthenticationController')
-const SessionManager = require('../Authentication/SessionManager')
-const NewsletterManager = require('../Newsletter/NewsletterManager')
-const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
-const _ = require('lodash')
-const { expressify } = require('@overleaf/promise-utils')
-const Features = require('../../infrastructure/Features')
-const SplitTestHandler = require('../SplitTests/SplitTestHandler')
-const Modules = require('../../infrastructure/Modules')
+import UserGetter from './UserGetter.js'
+import OError from '@overleaf/o-error'
+import UserSessionsManager from './UserSessionsManager.js'
+import logger from '@overleaf/logger'
+import Settings from '@overleaf/settings'
+import AuthenticationController from '../Authentication/AuthenticationController.js'
+import SessionManager from '../Authentication/SessionManager.js'
+import NewsletterManager from '../Newsletter/NewsletterManager.js'
+import SubscriptionLocator from '../Subscription/SubscriptionLocator.js'
+import _ from 'lodash'
+import { expressify } from '@overleaf/promise-utils'
+import Features from '../../infrastructure/Features.js'
+import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
+import Modules from '../../infrastructure/Modules.js'
 
 async function settingsPage(req, res) {
   const userId = SessionManager.getLoggedInUserId(req.session)
@@ -324,4 +324,4 @@ const UserPagesController = {
   },
 }
 
-module.exports = UserPagesController
+export default UserPagesController

+ 11 - 11
services/web/app/src/Features/UserMembership/UserMembershipController.js → services/web/app/src/Features/UserMembership/UserMembershipController.mjs

@@ -1,16 +1,16 @@
-const SessionManager = require('../Authentication/SessionManager')
-const UserMembershipHandler = require('./UserMembershipHandler')
-const Errors = require('../Errors/Errors')
-const EmailHelper = require('../Helpers/EmailHelper')
-const { csvAttachment } = require('../../infrastructure/Response')
-const {
+import SessionManager from '../Authentication/SessionManager.js'
+import UserMembershipHandler from './UserMembershipHandler.js'
+import Errors from '../Errors/Errors.js'
+import EmailHelper from '../Helpers/EmailHelper.js'
+import { csvAttachment } from '../../infrastructure/Response.js'
+import {
   UserIsManagerError,
   UserAlreadyAddedError,
   UserNotFoundError,
-} = require('./UserMembershipErrors')
-const { SSOConfig } = require('../../models/SSOConfig')
-const CSVParser = require('json2csv').Parser
-const { expressify } = require('@overleaf/promise-utils')
+} from './UserMembershipErrors.js'
+import { SSOConfig } from '../../models/SSOConfig.js'
+import { Parser as CSVParser } from 'json2csv'
+import { expressify } from '@overleaf/promise-utils'
 
 async function manageGroupMembers(req, res, next) {
   const { entity: subscription, entityConfig } = req
@@ -99,7 +99,7 @@ async function _renderManagersPage(req, res, next, template) {
   })
 }
 
-module.exports = {
+export default {
   manageGroupMembers: expressify(manageGroupMembers),
   manageGroupManagers: expressify(manageGroupManagers),
   manageInstitutionManagers: expressify(manageInstitutionManagers),

+ 7 - 7
services/web/app/src/Features/UserMembership/UserMembershipRouter.js → services/web/app/src/Features/UserMembership/UserMembershipRouter.mjs

@@ -1,9 +1,9 @@
-const UserMembershipMiddleware = require('./UserMembershipMiddleware')
-const UserMembershipController = require('./UserMembershipController')
-const SubscriptionGroupController = require('../Subscription/SubscriptionGroupController')
-const TeamInvitesController = require('../Subscription/TeamInvitesController')
-const { RateLimiter } = require('../../infrastructure/RateLimiter')
-const RateLimiterMiddleware = require('../Security/RateLimiterMiddleware')
+import UserMembershipMiddleware from './UserMembershipMiddleware.js'
+import UserMembershipController from './UserMembershipController.mjs'
+import SubscriptionGroupController from '../Subscription/SubscriptionGroupController.mjs'
+import TeamInvitesController from '../Subscription/TeamInvitesController.mjs'
+import { RateLimiter } from '../../infrastructure/RateLimiter.js'
+import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
 
 const rateLimiters = {
   createTeamInvite: new RateLimiter('create-team-invite', {
@@ -16,7 +16,7 @@ const rateLimiters = {
   }),
 }
 
-module.exports = {
+export default {
   apply(webRouter) {
     // group members routes
     webRouter.get(

+ 5 - 5
services/web/app/src/Features/V1/V1Handler.js → services/web/app/src/Features/V1/V1Handler.mjs

@@ -10,13 +10,13 @@
  * DS207: Consider shorter variations of null checks
  * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  */
+import OError from '@overleaf/o-error'
+import V1Api from './V1Api.js'
+import logger from '@overleaf/logger'
+
 let V1Handler
-const OError = require('@overleaf/o-error')
-const V1Api = require('./V1Api')
-const Settings = require('@overleaf/settings')
-const logger = require('@overleaf/logger')
 
-module.exports = V1Handler = {
+export default V1Handler = {
   authWithV1(email, password, callback) {
     return V1Api.request(
       {

+ 25 - 22
services/web/test/unit/src/BetaProgram/BetaProgramControllerTests.js → services/web/test/unit/src/BetaProgram/BetaProgramControllerTests.mjs

@@ -1,8 +1,11 @@
-const SandboxedModule = require('sandboxed-module')
-const path = require('path')
-const sinon = require('sinon')
-const { expect } = require('chai')
-const MockResponse = require('../helpers/MockResponse')
+import esmock from 'esmock'
+import path from 'node:path'
+import sinon from 'sinon'
+import { expect } from 'chai'
+import MockResponse from '../helpers/MockResponse.js'
+import { fileURLToPath } from 'node:url'
+
+const __dirname = fileURLToPath(new URL('.', import.meta.url))
 
 const modulePath = path.join(
   __dirname,
@@ -10,7 +13,7 @@ const modulePath = path.join(
 )
 
 describe('BetaProgramController', function () {
-  beforeEach(function () {
+  beforeEach(async function () {
     this.user = {
       _id: (this.user_id = 'a_simple_id'),
       email: 'user@example.com',
@@ -28,28 +31,28 @@ describe('BetaProgramController', function () {
         sessionMaintenance: sinon.stub(),
       },
     }
-    this.BetaProgramController = SandboxedModule.require(modulePath, {
-      requires: {
-        '../SplitTests/SplitTestSessionHandler': this.SplitTestSessionHandler,
-        './BetaProgramHandler': (this.BetaProgramHandler = {
+    this.BetaProgramController = await esmock.strict(modulePath, {
+      '../../../../app/src/Features/SplitTests/SplitTestSessionHandler':
+        this.SplitTestSessionHandler,
+      '../../../../app/src/Features/BetaProgram/BetaProgramHandler':
+        (this.BetaProgramHandler = {
           promises: {
             optIn: sinon.stub().resolves(),
             optOut: sinon.stub().resolves(),
           },
         }),
-        '../User/UserGetter': (this.UserGetter = {
-          promises: {
-            getUser: sinon.stub().resolves(),
-          },
+      '../../../../app/src/Features/User/UserGetter': (this.UserGetter = {
+        promises: {
+          getUser: sinon.stub().resolves(),
+        },
+      }),
+      '@overleaf/settings': (this.settings = {
+        languages: {},
+      }),
+      '../../../../app/src/Features/Authentication/AuthenticationController':
+        (this.AuthenticationController = {
+          getLoggedInUserId: sinon.stub().returns(this.user._id),
         }),
-        '@overleaf/settings': (this.settings = {
-          languages: {},
-        }),
-        '../Authentication/AuthenticationController':
-          (this.AuthenticationController = {
-            getLoggedInUserId: sinon.stub().returns(this.user._id),
-          }),
-      },
     })
     this.res = new MockResponse()
     this.next = sinon.stub()

+ 20 - 16
services/web/test/unit/src/BetaProgram/BetaProgramHandlerTests.js → services/web/test/unit/src/BetaProgram/BetaProgramHandlerTests.mjs

@@ -1,14 +1,19 @@
-const SandboxedModule = require('sandboxed-module')
-const path = require('path')
+import esmock from 'esmock'
+import path from 'node:path'
+
+import sinon from 'sinon'
+import { expect } from 'chai'
+import { fileURLToPath } from 'node:url'
+
+const __dirname = fileURLToPath(new URL('.', import.meta.url))
+
 const modulePath = path.join(
   __dirname,
   '../../../../app/src/Features/BetaProgram/BetaProgramHandler'
 )
-const sinon = require('sinon')
-const { expect } = require('chai')
 
 describe('BetaProgramHandler', function () {
-  beforeEach(function () {
+  beforeEach(async function () {
     this.user_id = 'some_id'
     this.user = {
       _id: this.user_id,
@@ -17,20 +22,19 @@ describe('BetaProgramHandler', function () {
       betaProgram: false,
       save: sinon.stub().callsArgWith(0, null),
     }
-    this.handler = SandboxedModule.require(modulePath, {
-      requires: {
-        '@overleaf/metrics': {
-          inc: sinon.stub(),
+    this.handler = await esmock.strict(modulePath, {
+      '@overleaf/metrics': {
+        inc: sinon.stub(),
+      },
+      '../../../../app/src/Features/User/UserUpdater': (this.UserUpdater = {
+        promises: {
+          updateUser: sinon.stub().resolves(),
         },
-        '../User/UserUpdater': (this.UserUpdater = {
-          promises: {
-            updateUser: sinon.stub().resolves(),
-          },
-        }),
-        '../Analytics/AnalyticsManager': (this.AnalyticsManager = {
+      }),
+      '../../../../app/src/Features/Analytics/AnalyticsManager':
+        (this.AnalyticsManager = {
           setUserPropertyForUserInBackground: sinon.stub(),
         }),
-      },
     })
   })