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

Merge pull request #10983 from overleaf/revert-10901-lg-openapi-chat

Revert "Migrate chat service to OpenAPI"

GitOrigin-RevId: 39bdfd98bc55f8d9d56fb18bb288749aa13f25e0
Lucie Germain 3 лет назад
Родитель
Сommit
7ed9b04c3c

+ 8 - 280
package-lock.json

@@ -1022,17 +1022,6 @@
       "name": "@overleaf/settings",
       "version": "3.0.0"
     },
-    "node_modules/@apidevtools/json-schema-ref-parser": {
-      "version": "9.0.9",
-      "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz",
-      "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==",
-      "dependencies": {
-        "@jsdevtools/ono": "^7.1.3",
-        "@types/json-schema": "^7.0.6",
-        "call-me-maybe": "^1.0.1",
-        "js-yaml": "^4.1.0"
-      }
-    },
     "node_modules/@arrows/array": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz",
@@ -5160,11 +5149,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/@jsdevtools/ono": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
-      "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="
-    },
     "node_modules/@juggle/resize-observer": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz",
@@ -10399,6 +10383,7 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
       "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+      "devOptional": true,
       "dependencies": {
         "ajv": "^8.0.0"
       },
@@ -10415,6 +10400,7 @@
       "version": "8.11.0",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
       "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+      "devOptional": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.1",
         "json-schema-traverse": "^1.0.0",
@@ -10429,7 +10415,8 @@
     "node_modules/ajv-formats/node_modules/json-schema-traverse": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "devOptional": true
     },
     "node_modules/ajv-keywords": {
       "version": "3.5.2",
@@ -12429,11 +12416,6 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
-    "node_modules/call-me-maybe": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
-      "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="
-    },
     "node_modules/callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -14765,11 +14747,6 @@
         "node": ">=4.0.0"
       }
     },
-    "node_modules/deep-freeze": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
-      "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg=="
-    },
     "node_modules/deep-is": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -16848,11 +16825,6 @@
         "node": ">=0.4.x"
       }
     },
-    "node_modules/events-listener": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz",
-      "integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g=="
-    },
     "node_modules/execa": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -16909,96 +16881,6 @@
         "node": ">=4"
       }
     },
-    "node_modules/exegesis": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.1.1.tgz",
-      "integrity": "sha512-PvSqaMOw2absLBgsthtJyVOeCHN4lxQ1dM7ibXb6TfZZJaoXtGELoEAGJRFvdN16+u9kg8oy1okZXRk8VpimWA==",
-      "dependencies": {
-        "@apidevtools/json-schema-ref-parser": "^9.0.3",
-        "ajv": "^8.3.0",
-        "ajv-formats": "^2.1.0",
-        "body-parser": "^1.18.3",
-        "content-type": "^1.0.4",
-        "deep-freeze": "0.0.1",
-        "events-listener": "^1.1.0",
-        "glob": "^7.1.3",
-        "json-ptr": "^3.0.1",
-        "json-schema-traverse": "^1.0.0",
-        "lodash": "^4.17.11",
-        "openapi3-ts": "^3.1.1",
-        "promise-breaker": "^6.0.0",
-        "pump": "^3.0.0",
-        "qs": "^6.6.0",
-        "raw-body": "^2.3.3",
-        "semver": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=6.0.0",
-        "npm": ">5.0.0"
-      }
-    },
-    "node_modules/exegesis-express": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/exegesis-express/-/exegesis-express-4.0.0.tgz",
-      "integrity": "sha512-V2hqwTtYRj0bj43K4MCtm0caD97YWkqOUHFMRCBW5L1x9IjyqOEc7Xa4oQjjiFbeFOSQzzwPV+BzXsQjSz08fw==",
-      "dependencies": {
-        "exegesis": "^4.1.0"
-      },
-      "engines": {
-        "node": ">=6.0.0",
-        "npm": ">5.0.0"
-      }
-    },
-    "node_modules/exegesis/node_modules/ajv": {
-      "version": "8.11.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
-      "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/exegesis/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
-    },
-    "node_modules/exegesis/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/exegesis/node_modules/semver": {
-      "version": "7.3.8",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
-      "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/exegesis/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
-    },
     "node_modules/exifr": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/exifr/-/exifr-6.3.0.tgz",
@@ -22538,11 +22420,6 @@
       "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
       "dev": true
     },
-    "node_modules/json-ptr": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.1.1.tgz",
-      "integrity": "sha512-SiSJQ805W1sDUCD1+/t1/1BIrveq2Fe9HJqENxZmMCILmrPI7WhS/pePpIOx85v6/H2z1Vy7AI08GV2TzfXocg=="
-    },
     "node_modules/json-refs": {
       "version": "3.0.15",
       "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz",
@@ -26919,22 +26796,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/openapi3-ts": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.2.tgz",
-      "integrity": "sha512-S8fijNOqe/ut0kEDAwHZnI7sVYqb8Q3XnISmSyXmK76jgrcf4ableI75KTY1qdksd9EI/t39Vi5M4VYKrkNKfQ==",
-      "dependencies": {
-        "yaml": "^2.1.3"
-      }
-    },
-    "node_modules/openapi3-ts/node_modules/yaml": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
-      "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
-      "engines": {
-        "node": ">= 14"
-      }
-    },
     "node_modules/openid-client": {
       "version": "3.15.10",
       "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-3.15.10.tgz",
@@ -28474,11 +28335,6 @@
         "asap": "~2.0.3"
       }
     },
-    "node_modules/promise-breaker": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-6.0.0.tgz",
-      "integrity": "sha512-BthzO9yTPswGf7etOBiHCVuugs2N01/Q/94dIPls48z2zCmrnDptUUZzfIb+41xq0MnYZ/BzmOd6ikDR4ibNZA=="
-    },
     "node_modules/promise.prototype.finally": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz",
@@ -35915,15 +35771,12 @@
     },
     "services/chat": {
       "name": "@overleaf/chat",
-      "version": "1.0.0",
-      "license": "ISC",
       "dependencies": {
         "@overleaf/logger": "*",
         "@overleaf/metrics": "*",
         "@overleaf/settings": "*",
         "async": "^3.2.2",
         "body-parser": "^1.19.0",
-        "exegesis-express": "^4.0.0",
         "express": "4.17.1",
         "mongodb": "^4.11.0"
       },
@@ -41744,17 +41597,6 @@
     }
   },
   "dependencies": {
-    "@apidevtools/json-schema-ref-parser": {
-      "version": "9.0.9",
-      "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz",
-      "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==",
-      "requires": {
-        "@jsdevtools/ono": "^7.1.3",
-        "@types/json-schema": "^7.0.6",
-        "call-me-maybe": "^1.0.1",
-        "js-yaml": "^4.1.0"
-      }
-    },
     "@arrows/array": {
       "version": "1.4.1",
       "resolved": "https://registry.npmjs.org/@arrows/array/-/array-1.4.1.tgz",
@@ -44959,11 +44801,6 @@
       "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
       "dev": true
     },
-    "@jsdevtools/ono": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
-      "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="
-    },
     "@juggle/resize-observer": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.1.tgz",
@@ -46919,7 +46756,6 @@
         "body-parser": "^1.19.0",
         "chai": "^4.3.6",
         "chai-as-promised": "^7.1.1",
-        "exegesis-express": "^4.0.0",
         "express": "4.17.1",
         "mocha": "^8.4.0",
         "mongodb": "^4.11.0",
@@ -53662,6 +53498,7 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
       "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+      "devOptional": true,
       "requires": {
         "ajv": "^8.0.0"
       },
@@ -53670,6 +53507,7 @@
           "version": "8.11.0",
           "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
           "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
+          "devOptional": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
             "json-schema-traverse": "^1.0.0",
@@ -53680,7 +53518,8 @@
         "json-schema-traverse": {
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+          "devOptional": true
         }
       }
     },
@@ -55252,11 +55091,6 @@
         "get-intrinsic": "^1.0.2"
       }
     },
-    "call-me-maybe": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
-      "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ=="
-    },
     "callsites": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -57095,11 +56929,6 @@
       "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
       "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
     },
-    "deep-freeze": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz",
-      "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg=="
-    },
     "deep-is": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -58693,11 +58522,6 @@
       "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
       "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
     },
-    "events-listener": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/events-listener/-/events-listener-1.1.0.tgz",
-      "integrity": "sha512-Kd3EgYfODHueq6GzVfs/VUolh2EgJsS8hkO3KpnDrxVjU3eq63eXM2ujXkhPP+OkeUOhL8CxdfZbQXzryb5C4g=="
-    },
     "execa": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
@@ -58738,77 +58562,6 @@
         "pify": "^2.2.0"
       }
     },
-    "exegesis": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/exegesis/-/exegesis-4.1.1.tgz",
-      "integrity": "sha512-PvSqaMOw2absLBgsthtJyVOeCHN4lxQ1dM7ibXb6TfZZJaoXtGELoEAGJRFvdN16+u9kg8oy1okZXRk8VpimWA==",
-      "requires": {
-        "@apidevtools/json-schema-ref-parser": "^9.0.3",
-        "ajv": "^8.3.0",
-        "ajv-formats": "^2.1.0",
-        "body-parser": "^1.18.3",
-        "content-type": "^1.0.4",
-        "deep-freeze": "0.0.1",
-        "events-listener": "^1.1.0",
-        "glob": "^7.1.3",
-        "json-ptr": "^3.0.1",
-        "json-schema-traverse": "^1.0.0",
-        "lodash": "^4.17.11",
-        "openapi3-ts": "^3.1.1",
-        "promise-breaker": "^6.0.0",
-        "pump": "^3.0.0",
-        "qs": "^6.6.0",
-        "raw-body": "^2.3.3",
-        "semver": "^7.0.0"
-      },
-      "dependencies": {
-        "ajv": {
-          "version": "8.11.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz",
-          "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==",
-          "requires": {
-            "fast-deep-equal": "^3.1.1",
-            "json-schema-traverse": "^1.0.0",
-            "require-from-string": "^2.0.2",
-            "uri-js": "^4.2.2"
-          }
-        },
-        "json-schema-traverse": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-          "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
-        },
-        "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "requires": {
-            "yallist": "^4.0.0"
-          }
-        },
-        "semver": {
-          "version": "7.3.8",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
-          "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
-          "requires": {
-            "lru-cache": "^6.0.0"
-          }
-        },
-        "yallist": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
-        }
-      }
-    },
-    "exegesis-express": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/exegesis-express/-/exegesis-express-4.0.0.tgz",
-      "integrity": "sha512-V2hqwTtYRj0bj43K4MCtm0caD97YWkqOUHFMRCBW5L1x9IjyqOEc7Xa4oQjjiFbeFOSQzzwPV+BzXsQjSz08fw==",
-      "requires": {
-        "exegesis": "^4.1.0"
-      }
-    },
     "exifr": {
       "version": "6.3.0",
       "resolved": "https://registry.npmjs.org/exifr/-/exifr-6.3.0.tgz",
@@ -63172,11 +62925,6 @@
       "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
       "dev": true
     },
-    "json-ptr": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/json-ptr/-/json-ptr-3.1.1.tgz",
-      "integrity": "sha512-SiSJQ805W1sDUCD1+/t1/1BIrveq2Fe9HJqENxZmMCILmrPI7WhS/pePpIOx85v6/H2z1Vy7AI08GV2TzfXocg=="
-    },
     "json-refs": {
       "version": "3.0.15",
       "resolved": "https://registry.npmjs.org/json-refs/-/json-refs-3.0.15.tgz",
@@ -66702,21 +66450,6 @@
         "is-wsl": "^2.2.0"
       }
     },
-    "openapi3-ts": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/openapi3-ts/-/openapi3-ts-3.1.2.tgz",
-      "integrity": "sha512-S8fijNOqe/ut0kEDAwHZnI7sVYqb8Q3XnISmSyXmK76jgrcf4ableI75KTY1qdksd9EI/t39Vi5M4VYKrkNKfQ==",
-      "requires": {
-        "yaml": "^2.1.3"
-      },
-      "dependencies": {
-        "yaml": {
-          "version": "2.1.3",
-          "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
-          "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg=="
-        }
-      }
-    },
     "openid-client": {
       "version": "3.15.10",
       "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-3.15.10.tgz",
@@ -68372,11 +68105,6 @@
         "asap": "~2.0.3"
       }
     },
-    "promise-breaker": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-6.0.0.tgz",
-      "integrity": "sha512-BthzO9yTPswGf7etOBiHCVuugs2N01/Q/94dIPls48z2zCmrnDptUUZzfIb+41xq0MnYZ/BzmOd6ikDR4ibNZA=="
-    },
     "promise.prototype.finally": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz",

+ 2 - 3
services/chat/app.js

@@ -1,14 +1,13 @@
 import logger from '@overleaf/logger'
 import settings from '@overleaf/settings'
 import { mongoClient } from './app/js/mongodb.js'
-import { createServer } from './app/js/server.js'
+import { server } from './app/js/server.js'
 
 const port = settings.internal.chat.port
 const host = settings.internal.chat.host
 mongoClient
   .connect()
-  .then(async () => {
-    const { server } = await createServer()
+  .then(() => {
     server.listen(port, host, function (err) {
       if (err) {
         logger.fatal({ err }, `Cannot bind to ${host}:${port}. Exiting.`)

+ 40 - 124
services/chat/app/js/Features/Messages/MessageHttpController.js

@@ -3,105 +3,24 @@ import * as MessageManager from './MessageManager.js'
 import * as MessageFormatter from './MessageFormatter.js'
 import * as ThreadManager from '../Threads/ThreadManager.js'
 import { ObjectId } from '../../mongodb.js'
+import { expressify } from '../../util/promises.js'
 
 const DEFAULT_MESSAGE_LIMIT = 50
 const MAX_MESSAGE_LENGTH = 10 * 1024 // 10kb, about 1,500 words
 
-async function readContext(context, req) {
-  req.body = context.requestBody
-  req.params = context.params.path
-  req.query = context.params.query
-  if (typeof req.params.projectId !== 'undefined') {
-    if (!ObjectId.isValid(req.params.projectId)) {
-      context.res.status(400).setBody('Invalid projectId')
-    }
-  }
-  if (typeof req.params.threadId !== 'undefined') {
-    if (!ObjectId.isValid(req.params.threadId)) {
-      context.res.status(400).setBody('Invalid threadId')
-    }
-  }
-}
-
-export async function callMessageHttpController(context, ControllerMethod) {
-  const req = {}
-  readContext(context, req)
-  if (context.res.statusCode !== 400) {
-    return await ControllerMethod(req, context.res)
-  } else {
-    return context.res.body
-  }
-}
-
-export async function getGlobalMessages(context) {
-  return await callMessageHttpController(context, _getGlobalMessages)
-}
-
-export async function sendGlobalMessage(context) {
-  return await callMessageHttpController(context, _sendGlobalMessage)
-}
-
-export async function sendMessage(context) {
-  return await callMessageHttpController(context, _sendThreadMessage)
-}
-
-export async function getThreads(context) {
-  return await callMessageHttpController(context, _getAllThreads)
-}
-
-export async function resolveThread(context) {
-  return await callMessageHttpController(context, _resolveThread)
-}
-
-export async function reopenThread(context) {
-  return await callMessageHttpController(context, _reopenThread)
-}
-
-export async function deleteThread(context) {
-  return await callMessageHttpController(context, _deleteThread)
-}
-
-export async function editMessage(context) {
-  return await callMessageHttpController(context, _editMessage)
-}
-
-export async function deleteMessage(context) {
-  return await callMessageHttpController(context, _deleteMessage)
-}
-
-export async function destroyProject(context) {
-  return await callMessageHttpController(context, _destroyProject)
-}
-
-export async function getStatus(context) {
-  const message = 'chat is alive'
-  context.res.status(200).setBody(message)
-  return message
-}
-
-const _getGlobalMessages = async (req, res) => {
+export const getGlobalMessages = expressify(async (req, res) => {
   await _getMessages(ThreadManager.GLOBAL_THREAD, req, res)
-}
+})
 
-async function _sendGlobalMessage(req, res) {
-  const { user_id: userId, content } = req.body
-  const { projectId } = req.params
-  return await _sendMessage(
-    userId,
-    projectId,
-    content,
-    ThreadManager.GLOBAL_THREAD,
-    res
-  )
-}
+export const sendGlobalMessage = expressify(async (req, res) => {
+  await _sendMessage(ThreadManager.GLOBAL_THREAD, req, res)
+})
 
-async function _sendThreadMessage(req, res) {
-  const { user_id: userId, content } = req.body
-  const { projectId, threadId } = req.params
-  return await _sendMessage(userId, projectId, content, threadId, res)
-}
+export const sendThreadMessage = expressify(async (req, res) => {
+  await _sendMessage(req.params.threadId, req, res)
+})
 
-const _getAllThreads = async (req, res) => {
+export const getAllThreads = expressify(async (req, res) => {
   const { projectId } = req.params
   logger.debug({ projectId }, 'getting all threads')
   const rooms = await ThreadManager.findAllThreadRooms(projectId)
@@ -109,32 +28,32 @@ const _getAllThreads = async (req, res) => {
   const messages = await MessageManager.findAllMessagesInRooms(roomIds)
   const threads = MessageFormatter.groupMessagesByThreads(rooms, messages)
   res.json(threads)
-}
+})
 
-const _resolveThread = async (req, res) => {
+export const resolveThread = expressify(async (req, res) => {
   const { projectId, threadId } = req.params
   const { user_id: userId } = req.body
   logger.debug({ userId, projectId, threadId }, 'marking thread as resolved')
   await ThreadManager.resolveThread(projectId, threadId, userId)
-  res.status(204)
-}
+  res.sendStatus(204)
+})
 
-const _reopenThread = async (req, res) => {
+export const reopenThread = expressify(async (req, res) => {
   const { projectId, threadId } = req.params
   logger.debug({ projectId, threadId }, 'reopening thread')
   await ThreadManager.reopenThread(projectId, threadId)
-  res.status(204)
-}
+  res.sendStatus(204)
+})
 
-const _deleteThread = async (req, res) => {
+export const deleteThread = expressify(async (req, res) => {
   const { projectId, threadId } = req.params
   logger.debug({ projectId, threadId }, 'deleting thread')
   const roomId = await ThreadManager.deleteThread(projectId, threadId)
   await MessageManager.deleteAllMessagesInRoom(roomId)
-  res.status(204)
-}
+  res.sendStatus(204)
+})
 
-const _editMessage = async (req, res) => {
+export const editMessage = expressify(async (req, res) => {
   const { content, userId } = req.body
   const { projectId, threadId, messageId } = req.params
   logger.debug({ projectId, threadId, messageId, content }, 'editing message')
@@ -147,21 +66,20 @@ const _editMessage = async (req, res) => {
     Date.now()
   )
   if (!found) {
-    res.status(404)
-    return
+    return res.sendStatus(404)
   }
-  res.status(204)
-}
+  res.sendStatus(204)
+})
 
-const _deleteMessage = async (req, res) => {
+export const deleteMessage = expressify(async (req, res) => {
   const { projectId, threadId, messageId } = req.params
   logger.debug({ projectId, threadId, messageId }, 'deleting message')
   const room = await ThreadManager.findOrCreateThread(projectId, threadId)
   await MessageManager.deleteMessage(room._id, messageId)
-  res.status(204)
-}
+  res.sendStatus(204)
+})
 
-const _destroyProject = async (req, res) => {
+export const destroyProject = expressify(async (req, res) => {
   const { projectId } = req.params
   logger.debug({ projectId }, 'destroying project')
   const rooms = await ThreadManager.findAllThreadRoomsAndGlobalThread(projectId)
@@ -170,24 +88,22 @@ const _destroyProject = async (req, res) => {
   await MessageManager.deleteAllMessagesInRooms(roomIds)
   logger.debug({ projectId }, 'deleting all threads in project')
   await ThreadManager.deleteAllThreadsInProject(projectId)
-  res.status(204)
-}
+  res.sendStatus(204)
+})
 
-async function _sendMessage(userId, projectId, content, clientThreadId, res) {
+async function _sendMessage(clientThreadId, req, res) {
+  const { user_id: userId, content } = req.body
+  const { projectId } = req.params
   if (!ObjectId.isValid(userId)) {
-    const message = 'Invalid userId'
-    res.status(400).setBody(message)
-    return message
+    return res.status(400).send('Invalid userId')
   }
   if (!content) {
-    const message = 'No content provided'
-    res.status(400).setBody(message)
-    return message
+    return res.status(400).send('No content provided')
   }
   if (content.length > MAX_MESSAGE_LENGTH) {
-    const message = `Content too long (> ${MAX_MESSAGE_LENGTH} bytes)`
-    res.status(400).setBody(message)
-    return message
+    return res
+      .status(400)
+      .send(`Content too long (> ${MAX_MESSAGE_LENGTH} bytes)`)
   }
   logger.debug(
     { clientThreadId, projectId, userId, content },
@@ -205,7 +121,7 @@ async function _sendMessage(userId, projectId, content, clientThreadId, res) {
   )
   message = MessageFormatter.formatMessageForClientSide(message)
   message.room_id = projectId
-  res.status(201).setBody(message)
+  res.status(201).send(message)
 }
 
 async function _getMessages(clientThreadId, req, res) {
@@ -237,5 +153,5 @@ async function _getMessages(clientThreadId, req, res) {
   let messages = await MessageManager.getMessages(threadObjectId, limit, before)
   messages = MessageFormatter.formatMessagesForClientSide(messages)
   logger.debug({ projectId, messages }, 'got messages')
-  res.status(200).setBody(messages)
+  res.status(200).send(messages)
 }

+ 65 - 0
services/chat/app/js/router.js

@@ -0,0 +1,65 @@
+import * as MessageHttpController from './Features/Messages/MessageHttpController.js'
+import { ObjectId } from './mongodb.js'
+
+export function route(app) {
+  app.param('projectId', function (req, res, next, projectId) {
+    if (ObjectId.isValid(projectId)) {
+      next()
+    } else {
+      res.status(400).send('Invalid projectId')
+    }
+  })
+
+  app.param('threadId', function (req, res, next, threadId) {
+    if (ObjectId.isValid(threadId)) {
+      next()
+    } else {
+      res.status(400).send('Invalid threadId')
+    }
+  })
+
+  // These are for backwards compatibility
+  app.get('/room/:projectId/messages', MessageHttpController.getGlobalMessages)
+  app.post('/room/:projectId/messages', MessageHttpController.sendGlobalMessage)
+
+  app.get(
+    '/project/:projectId/messages',
+    MessageHttpController.getGlobalMessages
+  )
+  app.post(
+    '/project/:projectId/messages',
+    MessageHttpController.sendGlobalMessage
+  )
+
+  app.post(
+    '/project/:projectId/thread/:threadId/messages',
+    MessageHttpController.sendThreadMessage
+  )
+  app.get('/project/:projectId/threads', MessageHttpController.getAllThreads)
+
+  app.post(
+    '/project/:projectId/thread/:threadId/messages/:messageId/edit',
+    MessageHttpController.editMessage
+  )
+  app.delete(
+    '/project/:projectId/thread/:threadId/messages/:messageId',
+    MessageHttpController.deleteMessage
+  )
+
+  app.post(
+    '/project/:projectId/thread/:threadId/resolve',
+    MessageHttpController.resolveThread
+  )
+  app.post(
+    '/project/:projectId/thread/:threadId/reopen',
+    MessageHttpController.reopenThread
+  )
+  app.delete(
+    '/project/:projectId/thread/:threadId',
+    MessageHttpController.deleteThread
+  )
+
+  app.delete('/project/:projectId', MessageHttpController.destroyProject)
+
+  app.get('/status', (req, res, next) => res.send('chat is alive'))
+}

+ 9 - 36
services/chat/app/js/server.js

@@ -2,45 +2,18 @@ import http from 'http'
 import metrics from '@overleaf/metrics'
 import logger from '@overleaf/logger'
 import express from 'express'
-import exegesisExpress from 'exegesis-express'
-import path from 'path'
-import { fileURLToPath } from 'url'
-import * as messagesController from './Features/Messages/MessageHttpController.js'
-
-const __dirname = fileURLToPath(new URL('.', import.meta.url))
+import bodyParser from 'body-parser'
+import * as Router from './router.js'
 
 metrics.initialize('chat')
 logger.initialize('chat')
 
-export async function createServer() {
-  const app = express()
-
-  // See https://github.com/exegesis-js/exegesis/blob/master/docs/Options.md
-  const options = {
-    controllers: { messagesController },
-    ignoreServers: true,
-    allowMissingControllers: false,
-  }
-
-  // const exegesisMiddleware = await exegesisExpress.middleware(
-  const exegesisMiddleware = await exegesisExpress.middleware(
-    path.resolve(__dirname, '../../chat.yaml'),
-    options
-  )
-
-  // If you have any body parsers, this should go before them.
-  app.use(exegesisMiddleware)
-
-  // Return a 404
-  app.use((req, res) => {
-    res.status(404).json({ message: `Not found` })
-  })
+export const app = express()
+export const server = http.createServer(app)
 
-  // Handle any unexpected errors
-  app.use((err, req, res, next) => {
-    res.status(500).json({ message: `Internal error: ${err.message}` })
-  })
+app.use(bodyParser.json())
+app.use(bodyParser.urlencoded({ extended: true }))
+app.use(metrics.http.monitor(logger))
+metrics.injectMetricsRoute(app)
 
-  const server = http.createServer(app)
-  return { app, server }
-}
+Router.route(app)

+ 0 - 317
services/chat/chat.yaml

@@ -1,317 +0,0 @@
-openapi: 3.1.0
-x-stoplight:
-  id: okoe8mh50pjec
-info:
-  title: chat
-  version: '1.0'
-servers:
-  - url: 'http://chat:3010'
-x-exegesis-controller: messagesController
-paths:
-  '/project/{projectId}/messages':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-    get:
-      summary: Get Global messages
-      tags: []
-      responses:
-        '201':
-          description: OK
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Message'
-      operationId: getGlobalMessages
-      description: Get global messages for the project with Project ID provided
-      parameters:
-        - schema:
-            type: string
-          in: query
-          name: before
-        - schema:
-            type: string
-          in: query
-          name: limit
-    post:
-      summary: Send Global message
-      operationId: sendGlobalMessage
-      responses:
-        '201':
-          description: OK
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/Message'
-            examples:
-              example-1:
-                value:
-                  user_id: string
-                  content: string
-        description: 'UserID and Content of the message to be posted. '
-      description: Send global message  for the project with Project ID provided
-  '/project/{projectId}/thread/{threadId}/messages':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: threadId
-        in: path
-        required: true
-    post:
-      summary: Send message
-      operationId: sendMessage
-      responses:
-        '201':
-          description: Created
-      description: Add a message to the thread with thread ID provided from the Project with Project ID provided.
-      requestBody:
-        content:
-          application/json:
-            schema:
-              $ref: '#/components/schemas/Message'
-        description: |-
-          JSON object with :
-          - user_id: Id of the user 
-          - content: Content of the message
-  '/project/{projectId}/threads':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-    get:
-      summary: Get Threads
-      tags: []
-      responses:
-        '200':
-          description: OK
-          content:
-            application/json:
-              schema:
-                type: array
-                items:
-                  $ref: '#/components/schemas/Thread'
-              examples: {}
-        '404':
-          description: Not Found
-      operationId: getThreads
-      description: Get the list of threads for the project with Project ID provided
-  '/project/{projectId}/thread/{threadId}/messages/{messageId}/edit':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: threadId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: messageId
-        in: path
-        required: true
-    post:
-      summary: Edit message
-      operationId: editMessage
-      responses:
-        '204':
-          description: No Content
-        '404':
-          description: Not Found
-      requestBody:
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                content:
-                  type: string
-                user_id:
-                  type: string
-                  readOnly: true
-              required:
-                - content
-            examples: {}
-        description: |-
-          JSON object with :
-          - content: Content of the message to edit
-          - user_id: Id of the user (optional)
-      description: |
-        Update message with Message ID provided from the Thread ID and Project ID provided
-  '/project/{projectId}/thread/{threadId}/messages/{messageId}':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: threadId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: messageId
-        in: path
-        required: true
-    delete:
-      summary: Delete message
-      operationId: deleteMessage
-      responses:
-        '204':
-          description: No Content
-      description: 'Delete message with Message ID provided, from the Thread with ThreadID and ProjectID provided'
-  '/project/{projectId}/thread/{threadId}/resolve':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: threadId
-        in: path
-        required: true
-    post:
-      summary: Resolve Thread
-      operationId: resolveThread
-      responses:
-        '204':
-          description: No Content
-      requestBody:
-        content:
-          application/json:
-            schema:
-              type: object
-              properties:
-                user_id:
-                  type: string
-              required:
-                - user_id
-        description: |-
-          JSON object with : 
-          - user_id: Id of the user.
-      description: Mark Thread with ThreadID and ProjectID provided owned by the user with UserID provided as resolved.
-  '/project/{projectId}/thread/{threadId}/reopen':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: threadId
-        in: path
-        required: true
-    post:
-      summary: Reopen Thread
-      operationId: reopenThread
-      responses:
-        '204':
-          description: No Content
-      description: |-
-        Reopen Thread with ThreadID and ProjectID provided. 
-        i.e unmark it as resolved.
-  '/project/{projectId}/thread/{threadId}':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-      - schema:
-          type: string
-        name: threadId
-        in: path
-        required: true
-    delete:
-      summary: Delete thread
-      operationId: deleteThread
-      responses:
-        '204':
-          description: No Content
-      description: Delete thread with ThreadID and ProjectID provided
-  '/project/{projectId}':
-    parameters:
-      - schema:
-          type: string
-        name: projectId
-        in: path
-        required: true
-    delete:
-      summary: Destroy project
-      operationId: destroyProject
-      responses:
-        '204':
-          description: No Content
-      description: 'Delete all threads from Project with Project ID provided, and all messages in those threads.'
-  /status:
-    get:
-      summary: Check status
-      tags: []
-      responses:
-        '200':
-          description: OK
-          content:
-            application/json:
-              schema:
-                type: string
-                description: chat is alive
-      operationId: getStatus
-      description: Check that the Chat service is alive
-    head:
-      summary: Check status
-      tags: []
-      responses:
-        '200':
-          description: OK
-          content:
-            application/json:
-              schema:
-                type: string
-                description: chat is alive
-      operationId: getStatus
-      description: Check that the Chat service is alive
-components:
-  schemas:
-    Message:
-      title: Message
-      x-stoplight:
-        id: ue9n1vvezlutw
-      type: object
-      examples:
-        - user_id: string
-        - content: string
-      properties:
-        user_id:
-          type: string
-        content:
-          type: string
-      required:
-        - user_id
-        - content
-    Thread:
-      title: Thread
-      x-stoplight:
-        id: 0ppt3jw4h5bua
-      type: array
-      items:
-        $ref: '#/components/schemas/Message'

+ 1 - 9
services/chat/package.json

@@ -22,7 +22,6 @@
     "@overleaf/settings": "*",
     "async": "^3.2.2",
     "body-parser": "^1.19.0",
-    "exegesis-express": "^4.0.0",
     "express": "4.17.1",
     "mongodb": "^4.11.0"
   },
@@ -36,12 +35,5 @@
     "sandboxed-module": "^2.0.4",
     "sinon": "^9.2.4",
     "timekeeper": "^2.2.0"
-  },
-  "version": "1.0.0",
-  "directories": {
-    "test": "test"
-  },
-  "keywords": [],
-  "author": "",
-  "license": "AGPL-3.0"
+  }
 }

+ 0 - 3
services/chat/test/acceptance/js/GettingMessagesTests.js

@@ -28,9 +28,6 @@ describe('Getting messages', async function () {
         content2
       )
       expect(response2.statusCode).to.equal(201)
-      const { response: response3, body } = await ChatClient.checkStatus()
-      expect(response3.statusCode).to.equal(200)
-      expect(body).to.equal('chat is alive')
     })
 
     it('should contain the messages and populated users when getting the messages', async function () {

+ 1 - 3
services/chat/test/acceptance/js/SendingAMessageTests.js

@@ -122,9 +122,7 @@ describe('Sending a message', async function () {
           null
         )
         expect(response.statusCode).to.equal(400)
-        // Exegesis is responding with validation errors. I can´t find a way to choose the validation error yet.
-        // expect(body).to.equal('No content provided')
-        expect(body.message).to.equal('Validation errors')
+        expect(body).to.equal('No content provided')
       })
     })
 

+ 10 - 5
services/chat/test/acceptance/js/helpers/ChatApp.js

@@ -1,15 +1,20 @@
-import { createServer } from '../../../../app/js/server.js'
-import { promisify } from 'util'
+import { server } from '../../../../app/js/server.js'
 
 export { db } from '../../../../app/js/mongodb.js'
 
 let serverPromise = null
+function startServer(resolve, reject) {
+  server.listen(3010, 'localhost', error => {
+    if (error) {
+      return reject(error)
+    }
+    resolve()
+  })
+}
 
 export async function ensureRunning() {
   if (!serverPromise) {
-    const { app } = await createServer()
-    const startServer = promisify(app.listen.bind(app))
-    serverPromise = startServer(3010, 'localhost')
+    serverPromise = new Promise(startServer)
   }
   return serverPromise
 }

+ 14 - 22
services/chat/test/acceptance/js/helpers/ChatClient.js

@@ -64,6 +64,20 @@ export async function resolveThread(projectId, threadId, userId) {
   })
 }
 
+export async function reopenThread(projectId, threadId) {
+  return asyncRequest({
+    method: 'post',
+    url: `/project/${projectId}/thread/${threadId}/reopen`,
+  })
+}
+
+export async function deleteThread(projectId, threadId) {
+  return asyncRequest({
+    method: 'delete',
+    url: `/project/${projectId}/thread/${threadId}`,
+  })
+}
+
 export async function editMessage(projectId, threadId, messageId, content) {
   return asyncRequest({
     method: 'post',
@@ -91,28 +105,6 @@ export async function editMessageWithUser(
   })
 }
 
-export async function checkStatus() {
-  return asyncRequest({
-    method: 'get',
-    url: `/status`,
-    json: true,
-  })
-}
-
-export async function reopenThread(projectId, threadId) {
-  return asyncRequest({
-    method: 'post',
-    url: `/project/${projectId}/thread/${threadId}/reopen`,
-  })
-}
-
-export async function deleteThread(projectId, threadId) {
-  return asyncRequest({
-    method: 'delete',
-    url: `/project/${projectId}/thread/${threadId}`,
-  })
-}
-
 export async function deleteMessage(projectId, threadId, messageId) {
   return asyncRequest({
     method: 'delete',