diff --git a/develop/docker-compose.dev.yml b/develop/docker-compose.dev.yml index 3d2fca7e0b..5315cddcc3 100644 --- a/develop/docker-compose.dev.yml +++ b/develop/docker-compose.dev.yml @@ -80,14 +80,14 @@ services: - ../services/history-v1/migrations:/overleaf/services/history-v1/migrations notifications: - command: ["node", "--watch", "app.js"] + command: ["node", "--watch", "app.ts"] environment: - NODE_OPTIONS=--inspect=0.0.0.0:9229 ports: - "127.0.0.1:9236:9229" volumes: - ../services/notifications/app:/overleaf/services/notifications/app - - ../services/notifications/app.js:/overleaf/services/notifications/app.js + - ../services/notifications/app.ts:/overleaf/services/notifications/app.ts - ../services/notifications/config:/overleaf/services/notifications/config project-history: diff --git a/libraries/metrics/http.js b/libraries/metrics/http.js index 43568526c2..a5c6e54779 100644 --- a/libraries/metrics/http.js +++ b/libraries/metrics/http.js @@ -75,4 +75,4 @@ class RequestLogger { } } -module.exports.monitor = monitor +module.exports = { monitor, RequestLogger } diff --git a/package-lock.json b/package-lock.json index 3a1b180695..3c790f2cc9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19307,6 +19307,16 @@ "@types/node": "*" } }, + "node_modules/@types/method-override": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/method-override/-/method-override-3.0.0.tgz", + "integrity": "sha512-7XFHR6j7JljprBpzzRZatakUXm1kEGAM3PL/GSsGRHtDvOAKYCdmnXX/5YSl1eQrpJymGs9tRekSWEGaG+Ntjw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/express": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -52114,6 +52124,7 @@ "zod-validation-error": "^4.0.1" }, "devDependencies": { + "@types/method-override": "^3.0.0", "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", diff --git a/server-ce/runit/notifications-overleaf/run b/server-ce/runit/notifications-overleaf/run index 1d0f2c8e00..0833487000 100755 --- a/server-ce/runit/notifications-overleaf/run +++ b/server-ce/runit/notifications-overleaf/run @@ -9,4 +9,4 @@ fi source /etc/overleaf/env.sh export LISTEN_ADDRESS=127.0.0.1 -exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /overleaf/services/notifications/app.js >> /var/log/overleaf/notifications.log 2>&1 +exec /sbin/setuser www-data /usr/bin/node $NODE_PARAMS /overleaf/services/notifications/app.ts >> /var/log/overleaf/notifications.log 2>&1 diff --git a/services/chat/tsconfig.json b/services/chat/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/chat/tsconfig.json +++ b/services/chat/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/clsi/tsconfig.json b/services/clsi/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/clsi/tsconfig.json +++ b/services/clsi/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/contacts/tsconfig.json b/services/contacts/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/contacts/tsconfig.json +++ b/services/contacts/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/docstore/tsconfig.json b/services/docstore/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/docstore/tsconfig.json +++ b/services/docstore/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/document-updater/tsconfig.json b/services/document-updater/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/document-updater/tsconfig.json +++ b/services/document-updater/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/filestore/tsconfig.json b/services/filestore/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/filestore/tsconfig.json +++ b/services/filestore/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/history-v1/tsconfig.json b/services/history-v1/tsconfig.json index 0e20309d3d..eef1c5c0ba 100644 --- a/services/history-v1/tsconfig.json +++ b/services/history-v1/tsconfig.json @@ -3,6 +3,7 @@ "include": [ "api/**/*", "app.js", + "app.ts", "app/js/**/*", "backup-deletion-app.mjs", "backup-verifier-app.mjs", diff --git a/services/notifications/Dockerfile b/services/notifications/Dockerfile index 1a6c6596e1..4f768a4355 100644 --- a/services/notifications/Dockerfile +++ b/services/notifications/Dockerfile @@ -24,4 +24,5 @@ COPY services/notifications/ /overleaf/services/notifications/ FROM app USER node -CMD ["node", "--expose-gc", "app.js"] +CMD ["node", "--expose-gc", "app.ts"] + diff --git a/services/notifications/app.js b/services/notifications/app.ts similarity index 90% rename from services/notifications/app.js rename to services/notifications/app.ts index 25caea0a47..71e5a12017 100644 --- a/services/notifications/app.js +++ b/services/notifications/app.ts @@ -3,7 +3,12 @@ import '@overleaf/metrics/initialize.js' import metrics from '@overleaf/metrics' import Settings from '@overleaf/settings' import logger from '@overleaf/logger' -import express from 'express' +import express, { + type Request, + type Response, + type ErrorRequestHandler, + type NextFunction, +} from 'express' import methodOverride from 'method-override' import { mongoClient } from './app/js/mongodb.js' import NotificationsController from './app/js/NotificationsController.ts' @@ -44,9 +49,12 @@ app.get('/health_check', HealthCheckController.check) app.get('*', (req, res) => res.sendStatus(404)) -app.use(handleApiError) - -function handleApiError(err, req, res, next) { +const handleApiError: ErrorRequestHandler = ( + err: Error, + req: Request, + res: Response, + next: NextFunction +) => { req.logger.addFields({ err }) if (err instanceof ParamsError) { req.logger.setLevel('warn') @@ -60,6 +68,8 @@ function handleApiError(err, req, res, next) { } } +app.use(handleApiError) + const host = Settings.internal.notifications?.host || '127.0.0.1' const port = Settings.internal.notifications?.port || 3042 try { diff --git a/services/notifications/buildscript.txt b/services/notifications/buildscript.txt index f0d52edcb4..dd00574061 100644 --- a/services/notifications/buildscript.txt +++ b/services/notifications/buildscript.txt @@ -8,4 +8,5 @@ notifications --public-repo=True --test-acceptance-vitest=True --test-unit-vitest=True +--ts-app=True --tsconfig-extra-includes=vitest.config.unit.cjs,vitest.config.acceptance.cjs diff --git a/services/notifications/package.json b/services/notifications/package.json index c3b8aeaa0b..7ca3a8fc90 100644 --- a/services/notifications/package.json +++ b/services/notifications/package.json @@ -2,10 +2,10 @@ "name": "@overleaf/notifications", "description": "An API to handle user notifications", "private": true, - "main": "app.js", + "main": "app.ts", "type": "module", "scripts": { - "start": "node app.js", + "start": "node app.ts", "test:acceptance:_run": "vitest --config ./vitest.config.acceptance.cjs", "test:acceptance": "npm run test:acceptance:_run", "test:unit:_run": "vitest --config ./vitest.config.unit.cjs", @@ -15,7 +15,7 @@ "format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'", "lint:fix": "eslint --fix .", "types:check": "tsc --noEmit", - "nodemon": "node --watch app.js" + "nodemon": "node --watch app.ts" }, "author": "", "license": "ISC", @@ -38,6 +38,7 @@ "zod-validation-error": "^4.0.1" }, "devDependencies": { + "@types/method-override": "^3.0.0", "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", diff --git a/services/notifications/test/acceptance/js/HealthCheck.test.ts b/services/notifications/test/acceptance/js/HealthCheck.test.ts index cae088b89f..1ffa60a5ef 100644 --- a/services/notifications/test/acceptance/js/HealthCheck.test.ts +++ b/services/notifications/test/acceptance/js/HealthCheck.test.ts @@ -1,6 +1,6 @@ import { beforeAll, describe, it, expect } from 'vitest' import { fetchStringWithResponse } from '@overleaf/fetch-utils' -import app from '../../../app.js' +import app from '../../../app.ts' import logger from '@overleaf/logger' let runAppPromise: Promise | null = null diff --git a/services/notifications/tsconfig.json b/services/notifications/tsconfig.json index d4cef19b98..c3d404fb34 100644 --- a/services/notifications/tsconfig.json +++ b/services/notifications/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/notifications/types/request.d.ts b/services/notifications/types/request.d.ts new file mode 100644 index 0000000000..1c51c095da --- /dev/null +++ b/services/notifications/types/request.d.ts @@ -0,0 +1,14 @@ +import 'express' +import RequestLogger from '@overleaf/metrics' + +// Add properties to Express's Request object that are defined in JS middleware +// or controllers and expected to be present in controllers. +declare global { + // eslint-disable-next-line no-unused-vars + namespace Express { + // eslint-disable-next-line no-unused-vars + interface Request { + logger: RequestLogger + } + } +} diff --git a/services/project-history/tsconfig.json b/services/project-history/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/project-history/tsconfig.json +++ b/services/project-history/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*", diff --git a/services/real-time/tsconfig.json b/services/real-time/tsconfig.json index d3fdd3022a..c018d6e682 100644 --- a/services/real-time/tsconfig.json +++ b/services/real-time/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../../tsconfig.backend.json", "include": [ "app.js", + "app.ts", "app/js/**/*", "benchmarks/**/*", "config/**/*",