Просмотр исходного кода

Upgrade Node.js from 22.18 to 24.13 (#30509)

GitOrigin-RevId: c2405a0583e68c61351f52b32ba28faec994fbc0
Anna Claire Fields 6 месяцев назад
Родитель
Сommit
e80ce42896
95 измененных файлов с 290 добавлено и 814 удалено
  1. 1 1
      libraries/access-token-encryptor/.nvmrc
  2. 1 1
      libraries/access-token-encryptor/buildscript.txt
  3. 1 1
      libraries/fetch-utils/.nvmrc
  4. 1 1
      libraries/fetch-utils/buildscript.txt
  5. 1 1
      libraries/fetch-utils/test/unit/FetchUtilsTests.js
  6. 14 5
      libraries/fetch-utils/test/unit/helpers/TestServer.js
  7. 1 1
      libraries/logger/.nvmrc
  8. 1 1
      libraries/logger/buildscript.txt
  9. 1 1
      libraries/metrics/.nvmrc
  10. 1 1
      libraries/metrics/buildscript.txt
  11. 1 1
      libraries/mongo-utils/.nvmrc
  12. 1 1
      libraries/mongo-utils/buildscript.txt
  13. 1 1
      libraries/o-error/.nvmrc
  14. 1 1
      libraries/o-error/buildscript.txt
  15. 1 1
      libraries/object-persistor/.nvmrc
  16. 1 1
      libraries/object-persistor/buildscript.txt
  17. 1 1
      libraries/overleaf-editor-core/.nvmrc
  18. 1 1
      libraries/overleaf-editor-core/buildscript.txt
  19. 1 1
      libraries/promise-utils/.nvmrc
  20. 1 1
      libraries/promise-utils/buildscript.txt
  21. 1 1
      libraries/ranges-tracker/.nvmrc
  22. 1 1
      libraries/ranges-tracker/buildscript.txt
  23. 1 1
      libraries/redis-wrapper/.nvmrc
  24. 1 1
      libraries/redis-wrapper/buildscript.txt
  25. 1 1
      libraries/settings/.nvmrc
  26. 1 1
      libraries/settings/buildscript.txt
  27. 1 1
      libraries/stream-utils/.nvmrc
  28. 1 1
      libraries/stream-utils/buildscript.txt
  29. 1 1
      libraries/validation-tools/.nvmrc
  30. 1 1
      libraries/validation-tools/buildscript.txt
  31. 13 682
      package-lock.json
  32. 1 1
      server-ce/test/Dockerfile
  33. 1 1
      services/chat/.nvmrc
  34. 1 1
      services/chat/Dockerfile
  35. 2 2
      services/chat/Makefile
  36. 1 1
      services/chat/buildscript.txt
  37. 2 2
      services/chat/docker-compose.yml
  38. 1 1
      services/clsi/.nvmrc
  39. 1 1
      services/clsi/Dockerfile
  40. 2 2
      services/clsi/Makefile
  41. 1 1
      services/clsi/buildscript.txt
  42. 1 1
      services/contacts/.nvmrc
  43. 1 1
      services/contacts/Dockerfile
  44. 2 2
      services/contacts/Makefile
  45. 1 1
      services/contacts/buildscript.txt
  46. 2 2
      services/contacts/docker-compose.yml
  47. 1 1
      services/docstore/.nvmrc
  48. 1 1
      services/docstore/Dockerfile
  49. 2 2
      services/docstore/Makefile
  50. 1 1
      services/docstore/buildscript.txt
  51. 2 2
      services/docstore/docker-compose.yml
  52. 1 1
      services/document-updater/.nvmrc
  53. 1 1
      services/document-updater/Dockerfile
  54. 2 2
      services/document-updater/Makefile
  55. 1 1
      services/document-updater/buildscript.txt
  56. 2 2
      services/document-updater/docker-compose.yml
  57. 1 1
      services/filestore/.nvmrc
  58. 1 1
      services/filestore/Dockerfile
  59. 2 2
      services/filestore/Makefile
  60. 1 1
      services/filestore/buildscript.txt
  61. 1 1
      services/filestore/docker-compose.ci.yml
  62. 1 1
      services/filestore/docker-compose.yml
  63. 1 1
      services/history-v1/.nvmrc
  64. 1 1
      services/history-v1/Dockerfile
  65. 2 2
      services/history-v1/Makefile
  66. 1 1
      services/history-v1/buildscript.txt
  67. 1 1
      services/history-v1/docker-compose.ci.yml
  68. 1 1
      services/history-v1/docker-compose.yml
  69. 1 1
      services/notifications/.nvmrc
  70. 1 1
      services/notifications/Dockerfile
  71. 2 2
      services/notifications/Makefile
  72. 1 1
      services/notifications/buildscript.txt
  73. 2 2
      services/notifications/docker-compose.yml
  74. 1 1
      services/project-history/.nvmrc
  75. 1 1
      services/project-history/Dockerfile
  76. 2 2
      services/project-history/Makefile
  77. 1 1
      services/project-history/buildscript.txt
  78. 2 2
      services/project-history/docker-compose.yml
  79. 0 1
      services/project-history/package.json
  80. 1 1
      services/real-time/.nvmrc
  81. 1 1
      services/real-time/Dockerfile
  82. 2 2
      services/real-time/Makefile
  83. 1 1
      services/real-time/buildscript.txt
  84. 2 2
      services/real-time/docker-compose.yml
  85. 1 1
      services/web/.nvmrc
  86. 1 1
      services/web/Dockerfile
  87. 1 1
      services/web/Dockerfile.frontend
  88. 1 1
      services/web/buildscript.txt
  89. 1 1
      services/web/docker-compose.common.env
  90. 2 2
      services/web/docker-compose.yml
  91. 1 1
      services/web/scripts/translations/Dockerfile
  92. 2 0
      services/web/test/frontend/features/editor-left-menu/components/actions-menu.test.tsx
  93. 1 0
      services/web/test/frontend/features/editor-left-menu/components/actions-word-count.test.tsx
  94. 1 0
      services/web/test/frontend/features/editor-left-menu/components/download-menu.test.tsx
  95. 153 20
      services/web/test/frontend/helpers/editor-providers.tsx

+ 1 - 1
libraries/access-token-encryptor/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/access-token-encryptor/buildscript.txt

@@ -4,6 +4,6 @@ access-token-encryptor
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/fetch-utils/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/fetch-utils/buildscript.txt

@@ -4,6 +4,6 @@ fetch-utils
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/fetch-utils/test/unit/FetchUtilsTests.js

@@ -22,7 +22,7 @@ const HTTP_PORT = 30001
 const HTTPS_PORT = 30002
 
 const attrs = [{ name: 'commonName', value: 'example.com' }]
-const pems = selfsigned.generate(attrs, { days: 365 })
+const pems = selfsigned.generate(attrs, { days: 365, keySize: 2048 })
 
 const PRIVATE_KEY = pems.private
 const PUBLIC_CERT = pems.cert

+ 14 - 5
libraries/fetch-utils/test/unit/helpers/TestServer.js

@@ -119,11 +119,20 @@ class TestServer {
   }
 
   stop() {
-    const stopHttp = promisify(this.server.close).bind(this.server)
-    const stopHttps = promisify(this.https_server.close).bind(this.https_server)
-    this.server.closeAllConnections()
-    this.https_server.closeAllConnections()
-    return Promise.all([stopHttp(), stopHttps()])
+    const promises = []
+    if (this.server) {
+      const stopHttp = promisify(this.server.close).bind(this.server)
+      this.server.closeAllConnections()
+      promises.push(stopHttp())
+    }
+    if (this.https_server) {
+      const stopHttps = promisify(this.https_server.close).bind(
+        this.https_server
+      )
+      this.https_server.closeAllConnections()
+      promises.push(stopHttps())
+    }
+    return Promise.all(promises)
   }
 }
 

+ 1 - 1
libraries/logger/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/logger/buildscript.txt

@@ -4,6 +4,6 @@ logger
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/metrics/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/metrics/buildscript.txt

@@ -4,6 +4,6 @@ metrics
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/mongo-utils/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/mongo-utils/buildscript.txt

@@ -4,6 +4,6 @@ mongo-utils
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/o-error/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/o-error/buildscript.txt

@@ -4,6 +4,6 @@ o-error
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/object-persistor/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/object-persistor/buildscript.txt

@@ -4,6 +4,6 @@ object-persistor
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/overleaf-editor-core/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/overleaf-editor-core/buildscript.txt

@@ -4,6 +4,6 @@ overleaf-editor-core
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🥑 Core
 --public-repo=False

+ 1 - 1
libraries/promise-utils/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/promise-utils/buildscript.txt

@@ -4,6 +4,6 @@ promise-utils
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/ranges-tracker/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/ranges-tracker/buildscript.txt

@@ -4,6 +4,6 @@ ranges-tracker
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🥑 Core
 --public-repo=False

+ 1 - 1
libraries/redis-wrapper/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/redis-wrapper/buildscript.txt

@@ -4,6 +4,6 @@ redis-wrapper
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/settings/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/settings/buildscript.txt

@@ -4,6 +4,6 @@ settings
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/stream-utils/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/stream-utils/buildscript.txt

@@ -4,6 +4,6 @@ stream-utils
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False

+ 1 - 1
libraries/validation-tools/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
libraries/validation-tools/buildscript.txt

@@ -4,7 +4,7 @@ validation-tools
 --env-pass-through=
 --esmock-loader=False
 --is-library=True
---node-version=22.18.0
+--node-version=24.13.0
 --public-repo=False
 --test-acceptance-vitest=True
 --test-unit-vitest=True

Разница между файлами не показана из-за своего большого размера
+ 13 - 682
package-lock.json


+ 1 - 1
server-ce/test/Dockerfile

@@ -1,4 +1,4 @@
-FROM node:22.18.0
+FROM node:24.13.0
 RUN curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - \
 &&  echo \
       "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \

+ 1 - 1
services/chat/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/chat/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/chat
 

+ 2 - 2
services/chat/Makefile

@@ -51,12 +51,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/chat/reports:/overleaf/services/chat/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/chat/buildscript.txt

@@ -3,6 +3,6 @@ chat
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🥑 Core
 --public-repo=False

+ 2 - 2
services/chat/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/chat
       - ../../node_modules:/overleaf/node_modules
@@ -26,7 +26,7 @@ services:
         condition: service_started
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/chat
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/clsi/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/clsi/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/clsi
 COPY services/clsi/install_deps.sh /overleaf/services/clsi/

+ 2 - 2
services/clsi/Makefile

@@ -51,12 +51,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/clsi/reports:/overleaf/services/clsi/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/clsi/buildscript.txt

@@ -4,7 +4,7 @@ clsi
 --env-add=ALLOWED_COMPILE_GROUPS="clsi-perf simple-latex-file",ENABLE_PDF_CACHING="true",PDF_CACHING_ENABLE_WORKER_POOL="true",ALLOWED_IMAGES=quay.io/sharelatex/texlive-full:2025.1,TEXLIVE_IMAGE=quay.io/sharelatex/texlive-full:2025.1,TEX_LIVE_IMAGE_NAME_OVERRIDE=us-east1-docker.pkg.dev/overleaf-ops/ol-docker,TEXLIVE_IMAGE_USER="tex",SANDBOXED_COMPILES="true",SANDBOXED_COMPILES_HOST_DIR_COMPILES=$PWD/compiles,SANDBOXED_COMPILES_HOST_DIR_OUTPUT=$PWD/output
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=True
 --test-unit-vitest=True

+ 1 - 1
services/contacts/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/contacts/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/contacts
 

+ 2 - 2
services/contacts/Makefile

@@ -51,12 +51,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/contacts/reports:/overleaf/services/contacts/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/contacts/buildscript.txt

@@ -3,6 +3,6 @@ contacts
 --env-add=
 --env-pass-through=
 --esmock-loader=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=B2C
 --public-repo=False

+ 2 - 2
services/contacts/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/contacts
       - ../../node_modules:/overleaf/node_modules
@@ -26,7 +26,7 @@ services:
         condition: service_started
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/contacts
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/docstore/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/docstore/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/docstore
 

+ 2 - 2
services/docstore/Makefile

@@ -53,12 +53,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/docstore/reports:/overleaf/services/docstore/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/docstore/buildscript.txt

@@ -3,7 +3,7 @@ docstore
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=True
 --test-unit-vitest=True

+ 2 - 2
services/docstore/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/docstore
       - ../../node_modules:/overleaf/node_modules
@@ -27,7 +27,7 @@ services:
         condition: service_started
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/docstore
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/document-updater/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/document-updater/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/document-updater
 

+ 2 - 2
services/document-updater/Makefile

@@ -54,12 +54,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/document-updater/reports:/overleaf/services/document-updater/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/document-updater/buildscript.txt

@@ -3,6 +3,6 @@ document-updater
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🥑 Core
 --public-repo=True

+ 2 - 2
services/document-updater/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/document-updater
       - ../../node_modules:/overleaf/node_modules
@@ -33,7 +33,7 @@ services:
         condition: service_healthy
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/document-updater
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/filestore/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/filestore/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/filestore
 COPY services/filestore/install_deps.sh /overleaf/services/filestore/

+ 2 - 2
services/filestore/Makefile

@@ -51,12 +51,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/filestore/reports:/overleaf/services/filestore/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/filestore/buildscript.txt

@@ -4,7 +4,7 @@ filestore
 --env-add=ENABLE_CONVERSIONS="true",USE_PROM_METRICS="true",AWS_S3_USER_FILES_STORAGE_CLASS=REDUCED_REDUNDANCY,AWS_S3_USER_FILES_BUCKET_NAME=fake-user-files,AWS_S3_USER_FILES_DEK_BUCKET_NAME=fake-user-files-dek,AWS_S3_TEMPLATE_FILES_BUCKET_NAME=fake-template-files,GCS_USER_FILES_BUCKET_NAME=fake-gcs-user-files,GCS_TEMPLATE_FILES_BUCKET_NAME=fake-gcs-template-files
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=True
 --test-acceptance-shards=SHARD_01_,SHARD_02_,SHARD_03_

+ 1 - 1
services/filestore/docker-compose.ci.yml

@@ -75,7 +75,7 @@ services:
   certs:
     build:
       dockerfile_inline: |
-        FROM node:22.18.0
+        FROM node:24.13.0
         RUN wget -O /certgen "https://github.com/minio/certgen/releases/download/v1.3.0/certgen-linux-"`dpkg --print-architecture`
         RUN chmod +x /certgen
     volumes:

+ 1 - 1
services/filestore/docker-compose.yml

@@ -77,7 +77,7 @@ services:
   certs:
     build:
       dockerfile_inline: |
-        FROM node:22.18.0
+        FROM node:24.13.0
         RUN wget -O /certgen "https://github.com/minio/certgen/releases/download/v1.3.0/certgen-linux-"`dpkg --print-architecture`
         RUN chmod +x /certgen
     volumes:

+ 1 - 1
services/history-v1/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/history-v1/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/history-v1
 COPY services/history-v1/install_deps.sh /overleaf/services/history-v1/

+ 2 - 2
services/history-v1/Makefile

@@ -56,12 +56,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/history-v1/reports:/overleaf/services/history-v1/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/history-v1/buildscript.txt

@@ -3,7 +3,7 @@ history-v1
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🥑 Core
 --public-repo=False
 --tsconfig-extra-includes=backup-deletion-app.mjs,backup-verifier-app.mjs,backup-worker-app.mjs,api/**/*,migrations/**/*,storage/**/*

+ 1 - 1
services/history-v1/docker-compose.ci.yml

@@ -124,7 +124,7 @@ services:
   certs:
     build:
       dockerfile_inline: |
-        FROM node:22.18.0
+        FROM node:24.13.0
         RUN wget -O /certgen "https://github.com/minio/certgen/releases/download/v1.3.0/certgen-linux-"`dpkg --print-architecture`
         RUN chmod +x /certgen
     volumes:

+ 1 - 1
services/history-v1/docker-compose.yml

@@ -130,7 +130,7 @@ services:
   certs:
     build:
       dockerfile_inline: |
-        FROM node:22.18.0
+        FROM node:24.13.0
         RUN wget -O /certgen "https://github.com/minio/certgen/releases/download/v1.3.0/certgen-linux-"`dpkg --print-architecture`
         RUN chmod +x /certgen
     volumes:

+ 1 - 1
services/notifications/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/notifications/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/notifications
 

+ 2 - 2
services/notifications/Makefile

@@ -52,12 +52,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/notifications/reports:/overleaf/services/notifications/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/notifications/buildscript.txt

@@ -3,7 +3,7 @@ notifications
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=True
 --test-acceptance-vitest=True

+ 2 - 2
services/notifications/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/notifications
       - ../../node_modules:/overleaf/node_modules
@@ -27,7 +27,7 @@ services:
         condition: service_started
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/notifications
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/project-history/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/project-history/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/project-history
 

+ 2 - 2
services/project-history/Makefile

@@ -54,12 +54,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/document-updater/app/js/types.ts:/overleaf/services/document-updater/app/js/types.ts --volume $(MONOREPO)/services/project-history/reports:/overleaf/services/project-history/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/project-history/buildscript.txt

@@ -3,6 +3,6 @@ project-history
 --env-add=
 --env-pass-through=
 --esmock-loader=True
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🥑 Core
 --public-repo=False

+ 2 - 2
services/project-history/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/project-history
       - ../../node_modules:/overleaf/node_modules
@@ -33,7 +33,7 @@ services:
         condition: service_healthy
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/project-history
       - ../../node_modules:/overleaf/node_modules

+ 0 - 1
services/project-history/package.json

@@ -32,7 +32,6 @@
     "bunyan": "^1.8.15",
     "celebrate": "^15.0.3",
     "diff-match-patch": "overleaf/diff-match-patch#89805f9c671a77a263fc53461acd62aa7498f688",
-    "esmock": "^2.6.3",
     "express": "4.22.1",
     "lodash": "^4.17.20",
     "minimist": "^1.2.8",

+ 1 - 1
services/real-time/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/real-time/Dockerfile

@@ -2,7 +2,7 @@
 # Instead run bin/update_build_scripts from
 # https://github.com/overleaf/internal/
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/real-time
 

+ 2 - 2
services/real-time/Makefile

@@ -50,12 +50,12 @@ clean:
 
 # Run the linting commands in the scope of the monorepo.
 # Eslint and prettier (plus some configs) are on the root.
-RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent
+RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:24.13.0 npm run --silent
 
 RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/real-time/reports:/overleaf/services/real-time/reports $(IMAGE_CI) npm run --silent
 
 # Same but from the top of the monorepo
-RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent
+RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:24.13.0 npm run --silent
 
 SHELLCHECK_OPTS = \
 	--shell=bash \

+ 1 - 1
services/real-time/buildscript.txt

@@ -3,7 +3,7 @@ real-time
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --pipeline-owner=🚉 Platform
 --public-repo=False
 --test-unit-vitest=True

+ 2 - 2
services/real-time/docker-compose.yml

@@ -4,7 +4,7 @@
 
 services:
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/real-time
       - ../../node_modules:/overleaf/node_modules
@@ -29,7 +29,7 @@ services:
         condition: service_healthy
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/real-time
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/web/.nvmrc

@@ -1 +1 @@
-22.18.0
+24.13.0

+ 1 - 1
services/web/Dockerfile

@@ -1,7 +1,7 @@
 # This file was auto-generated, do not edit it directly.
 # Instead run internal$ services/web/build_scripts
 
-FROM node:22.18.0 AS base
+FROM node:24.13.0 AS base
 
 WORKDIR /overleaf/services/web
 

+ 1 - 1
services/web/Dockerfile.frontend

@@ -1,4 +1,4 @@
-FROM node:22.18.0
+FROM node:24.13.0
 
 # Install Google Chrome
 RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -

+ 1 - 1
services/web/buildscript.txt

@@ -4,5 +4,5 @@ web
 --env-add=
 --env-pass-through=
 --esmock-loader=False
---node-version=22.18.0
+--node-version=24.13.0
 --public-repo=False

+ 1 - 1
services/web/docker-compose.common.env

@@ -45,6 +45,6 @@ OVERLEAF_SAML_IS_ADMIN_FIELD_VALUE=Brookes
 OVERLEAF_SAML_CERT=MIIDXTCCAkWgAwIBAgIJAOvOeQ4xFTzsMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNVBAYTAkdCMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTYxMTE1MTQxMjU5WhcNMjYxMTE1MTQxMjU5WjBFMQswCQYDVQQGEwJHQjETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCT6MBe5G9VoLU8MfztOEbUhnwLp17ak8eFUqxqeXkkqtWB0b/cmIBU3xoQoO3dIF8PBzfqehqfYVhrNt/TFgcmDfmJnPJRL1RJWMW3VmiP5odJ3LwlkKbZpkeT3wZ8HEJIR1+zbpxiBNkbd2GbdR1iumcsHzMYX1A2CBj+ZMV5VijC+K4P0e9c05VsDEUtLmfeAasJAiumQoVVgAe/BpiXjICGGewa6EPFI7mKkifIRKOGxdRESwZZjxP30bI31oDN0cgKqIgSJtJ9nfCn9jgBMBkQHu42WMuaWD4jrGd7+vYdX+oIfArs9aKgAH5kUGhGdew2R9SpBefrhbNxG8QIDAQABo1AwTjAdBgNVHQ4EFgQU+aSojSyyLChP/IpZcafvSdhj7KkwHwYDVR0jBBgwFoAU+aSojSyyLChP/IpZcafvSdhj7KkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEABl3+OOVLBWMKs6PjA8lPuloWDNzSr3v76oUcHqAb+cfbucjXrOVsS9RJ0X9yxvCQyfM9FfY43DbspnN3izYhdvbJD8kKLNf0LA5st+ZxLfy0ACyL2iyAwICaqndqxAjQYplFAHmpUiu1DiHckyBPekokDJd+ze95urHMOsaGS5RWPoKJVE0bkaAeZCmEu0NNpXRSBiuxXSTeSAJfv6kyE/rkdhzUKyUl/cGQFrsVYfAFQVA+W6CKOh74ErSEzSHQQYndl7nD33snD/YqdU1ROxV6aJzLKCg+sdj+wRXSP2u/UHnM4jW9TGJfhO42jzL6WVuEvr9q4l7zWzUQKKKhtQ==
 # DEVICE_HISTORY_SECRET has been generated using:
 # NOTE: crypto.generateKeySync was added in v15, v16 is the next LTS release.
-# $ docker run --rm node:22.18.0 --print 'require("crypto").generateKeySync("aes", { length: 256 }).export().toString("hex")'
+# $ docker run --rm node:24.13.0 --print 'require("crypto").generateKeySync("aes", { length: 256 }).export().toString("hex")'
 DEVICE_HISTORY_SECRET=1b46e6cdf72db02845da06c9517c9cfbbfa0d87357479f4e1df3ce160bd54807
 QUEUE_PROCESSING_ENABLED=true

+ 2 - 2
services/web/docker-compose.yml

@@ -4,7 +4,7 @@ volumes:
 services:
 
   test_unit:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/web
       - ../../node_modules:/overleaf/node_modules
@@ -32,7 +32,7 @@ services:
       - redis_test
 
   test_acceptance:
-    image: node:22.18.0
+    image: node:24.13.0
     volumes:
       - .:/overleaf/services/web
       - ../../node_modules:/overleaf/node_modules

+ 1 - 1
services/web/scripts/translations/Dockerfile

@@ -1,4 +1,4 @@
-FROM node:22.18.0
+FROM node:24.13.0
 
 WORKDIR /app/scripts/translations
 

+ 2 - 0
services/web/test/frontend/features/editor-left-menu/components/actions-menu.test.tsx

@@ -29,6 +29,7 @@ describe('<ActionsMenu />', function () {
 
     renderWithEditorContext(<ActionsMenu />, {
       projectId: '123abc',
+      mockCompileOnLoad: true,
       scope: {
         editor: {
           sharejs_doc: {
@@ -56,6 +57,7 @@ describe('<ActionsMenu />', function () {
 
     renderWithEditorContext(<ActionsMenu />, {
       projectId: '123abc',
+      mockCompileOnLoad: true,
       scope: {
         editor: {
           sharejs_doc: {

+ 1 - 0
services/web/test/frontend/features/editor-left-menu/components/actions-word-count.test.tsx

@@ -38,6 +38,7 @@ describe('<ActionsWordCount />', function () {
 
     renderWithEditorContext(<ActionsWordCount />, {
       projectId: '123abc',
+      mockCompileOnLoad: true,
       scope: {
         editor: {
           sharejs_doc: {

+ 1 - 0
services/web/test/frontend/features/editor-left-menu/components/download-menu.test.tsx

@@ -27,6 +27,7 @@ describe('<DownloadMenu />', function () {
 
     renderWithEditorContext(<DownloadMenu />, {
       projectId: '123abc',
+      mockCompileOnLoad: true,
       scope: {
         editor: {
           sharejs_doc: {

+ 153 - 20
services/web/test/frontend/helpers/editor-providers.tsx

@@ -49,6 +49,8 @@ import { UserId } from '../../../types/user'
 import { ProjectCompiler } from '../../../types/project-settings'
 import { ReferencesContext } from '@/features/ide-react/context/references-context'
 import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics'
+import { DetachCompileContext } from '@/shared/context/detach-compile-context'
+import { type CompileContext } from '@/shared/context/local-compile-context'
 
 // these constants can be imported in tests instead of
 // using magic strings
@@ -91,6 +93,7 @@ export type EditorProvidersProps = {
   layoutContext?: Partial<LayoutContextValue>
   userSettings?: Record<string, any>
   providers?: Record<string, React.FC<React.PropsWithChildren<any>>>
+  mockCompileOnLoad?: boolean
 }
 
 export const projectDefaults: ProjectMetadata = {
@@ -174,6 +177,7 @@ export function EditorProviders({
   layoutContext = layoutContextDefault,
   userSettings = {},
   providers = {},
+  mockCompileOnLoad = false,
 }: EditorProvidersProps) {
   window.metaAttributesCache.set(
     'ol-gitBridgePublicBaseUrl',
@@ -234,27 +238,32 @@ export function EditorProviders({
   window.metaAttributesCache.set('ol-user', { ...user, features })
   window.metaAttributesCache.set('ol-project_id', projectId)
 
+  const customProviders: Record<string, FC<PropsWithChildren>> = {
+    ConnectionProvider: makeConnectionProvider(socket),
+    IdeReactProvider: makeIdeReactProvider(scope, socket),
+    EditorOpenDocProvider: makeEditorOpenDocProvider({
+      currentDocumentId: scope.editor.currentDocumentId,
+      openDocName: scope.editor.openDocName,
+      currentDocument: scope.editor.sharejs_doc,
+    }),
+    EditorPropertiesProvider: makeEditorPropertiesProvider({
+      wantTrackChanges: scope.editor.wantTrackChanges,
+    }),
+    LayoutProvider: makeLayoutProvider(layoutContext),
+    ProjectProvider: makeProjectProvider(project),
+    ReferencesProvider: makeReferencesProvider(),
+    ...providers,
+  }
+
+  // Only override DetachCompileProvider when we need the mock
+  if (mockCompileOnLoad) {
+    customProviders.DetachCompileProvider =
+      makeDetachCompileProvider(mockCompileOnLoad)
+  }
+  // Otherwise, let ReactContextRoot use the real DetachCompileProvider from production
+
   return (
-    <ReactContextRoot
-      providers={{
-        ConnectionProvider: makeConnectionProvider(socket),
-        IdeReactProvider: makeIdeReactProvider(scope, socket),
-        EditorOpenDocProvider: makeEditorOpenDocProvider({
-          currentDocumentId: scope.editor.currentDocumentId,
-          openDocName: scope.editor.openDocName,
-          currentDocument: scope.editor.sharejs_doc,
-        }),
-        EditorPropertiesProvider: makeEditorPropertiesProvider({
-          wantTrackChanges: scope.editor.wantTrackChanges,
-        }),
-        LayoutProvider: makeLayoutProvider(layoutContext),
-        ProjectProvider: makeProjectProvider(project),
-        ReferencesProvider: makeReferencesProvider(),
-        ...providers,
-      }}
-    >
-      {children}
-    </ReactContextRoot>
+    <ReactContextRoot providers={customProviders}>{children}</ReactContextRoot>
   )
 }
 
@@ -640,3 +649,127 @@ export function makeProjectProvider(initialProject: ProjectMetadata) {
 
   return ProjectProvider
 }
+
+const BASE_COMPILE_CONTEXT_MOCK = {
+  animateCompileDropdownArrow: false,
+  clearCache: () => {},
+  clearingCache: false,
+  clsiServerId: undefined,
+  codeCheckFailed: false,
+  deliveryLatencies: {},
+  editedSinceCompileStarted: false,
+  fileList: undefined,
+  hasChanges: false,
+  hasShortCompileTimeout: false,
+  highlights: undefined,
+  isProjectOwner: true,
+  lastCompileOptions: {},
+  logEntryAnnotations: undefined,
+  logEntries: undefined,
+  outputFilesArchive: undefined,
+  pdfViewer: 'pdfjs',
+  position: undefined,
+  rawLog: undefined,
+  recompileFromScratch: () => {},
+  setAnimateCompileDropdownArrow: () => {},
+  setHasLintingError: () => {},
+  setHighlights: () => {},
+  setPosition: () => {},
+  setShowCompileTimeWarning: () => {},
+  setShowLogs: () => {},
+  toggleLogs: () => {},
+  setStopOnValidationError: () => {},
+  showLogs: false,
+  showCompileTimeWarning: false,
+  stopCompile: () => {},
+  stopOnValidationError: true,
+  stoppedOnFirstError: false,
+  uncompiled: false,
+  validationIssues: undefined,
+  firstRenderDone: () => {},
+  setChangedAt: () => {},
+  cleanupCompileResult: undefined,
+  syncToEntry: () => {},
+  recordAction: () => {},
+  darkModePdf: false,
+  setDarkModePdf: () => {},
+  activeOverallTheme: 'light',
+} as const
+
+const makeDetachCompileProvider = (mockCompileOnLoad: boolean = false) => {
+  const DetachCompileProvider: FC<PropsWithChildren> = ({ children }) => {
+    const [pdfUrl, setPdfUrl] = useState<string | undefined>()
+    const [pdfDownloadUrl, setPdfDownloadUrl] = useState<string | undefined>()
+    const [pdfFile, setPdfFile] = useState<any>()
+    const [compiling, setCompiling] = useState(false)
+    const [error, setError] = useState<string | undefined>()
+    const [autoCompile, setAutoCompile] = useState(true)
+    const [draft, setDraft] = useState(false)
+    const [stopOnFirstError, setStopOnFirstError] = useState(false)
+
+    const startCompile = useCallback(async () => {
+      setCompiling(true)
+      try {
+        const response = await fetch('/project/123abc/compile', {
+          method: 'POST',
+        })
+        const data = await response.json()
+        const pdfFileData = data.outputFiles?.find(
+          (file: any) => file.type === 'pdf'
+        )
+        if (data.status === 'success' && pdfFileData) {
+          const newPdfUrl = `${data.pdfDownloadDomain || ''}${pdfFileData.url}`
+          const params = [
+            data.compileGroup && `compileGroup=${data.compileGroup}`,
+            data.clsiServerId && `clsiserverid=${data.clsiServerId}`,
+            'popupDownload=true',
+          ]
+            .filter(Boolean)
+            .join('&')
+          const newPdfDownloadUrl = `/download/project/123abc/build/${pdfFileData.build}/output/${pdfFileData.path}?${params}`
+
+          setPdfUrl(newPdfUrl)
+          setPdfDownloadUrl(newPdfDownloadUrl)
+          setPdfFile({ pdfUrl: newPdfUrl, pdfDownloadUrl: newPdfDownloadUrl })
+        }
+      } catch (err) {
+        setError('Compile failed')
+      } finally {
+        setCompiling(false)
+      }
+    }, [])
+
+    useEffect(() => {
+      if (mockCompileOnLoad) {
+        startCompile()
+      }
+      // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [startCompile])
+
+    const value = {
+      ...BASE_COMPILE_CONTEXT_MOCK,
+      autoCompile,
+      compiling,
+      draft,
+      error,
+      pdfDownloadUrl,
+      pdfFile,
+      pdfUrl,
+      setAutoCompile,
+      setCompiling,
+      setDraft,
+      setError,
+      setStopOnFirstError,
+      startCompile,
+      stopOnFirstError,
+    } as CompileContext
+
+    return (
+      <DetachCompileContext.Provider value={value}>
+        {children}
+      </DetachCompileContext.Provider>
+    )
+  }
+
+  return DetachCompileProvider
+}

Некоторые файлы не были показаны из-за большого количества измененных файлов