diff --git a/api_tests/package.json b/api_tests/package.json index 647e35f9b..6729c596d 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -22,19 +22,20 @@ "api-test-tags": "jest -i tags.spec.ts" }, "devDependencies": { - "@eslint/js": "^9.25.1", + "@eslint/js": "^9.26.0", "@types/jest": "^29.5.12", - "@types/node": "^22.15.3", - "@typescript-eslint/eslint-plugin": "^8.31.0", - "@typescript-eslint/parser": "^8.31.0", - "eslint": "^9.25.1", - "eslint-plugin-prettier": "^5.2.6", + "@types/node": "^22.15.14", + "@typescript-eslint/eslint-plugin": "^8.32.0", + "@typescript-eslint/parser": "^8.32.0", + "eslint": "^9.26.0", + "eslint-plugin-prettier": "^5.4.0", "jest": "^29.5.0", - "lemmy-js-client": "1.0.0-remove-page-limit.1", + "joi": "^17.13.3", + "lemmy-js-client": "1.0.0-local-image-user.3", "prettier": "^3.5.3", "ts-jest": "^29.3.2", "tsoa": "^6.6.0", "typescript": "^5.8.3", - "typescript-eslint": "^8.31.0" + "typescript-eslint": "^8.32.0" } } diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index c1da07afc..5bd24753b 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -9,38 +9,41 @@ importers: .: devDependencies: '@eslint/js': - specifier: ^9.25.1 - version: 9.25.1 + specifier: ^9.26.0 + version: 9.26.0 '@types/jest': specifier: ^29.5.12 version: 29.5.14 '@types/node': - specifier: ^22.15.3 - version: 22.15.3 + specifier: ^22.15.14 + version: 22.15.14 '@typescript-eslint/eslint-plugin': - specifier: ^8.31.0 - version: 8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3) + specifier: ^8.32.0 + version: 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) '@typescript-eslint/parser': - specifier: ^8.31.0 - version: 8.31.1(eslint@9.25.1)(typescript@5.8.3) + specifier: ^8.32.0 + version: 8.32.0(eslint@9.26.0)(typescript@5.8.3) eslint: - specifier: ^9.25.1 - version: 9.25.1 + specifier: ^9.26.0 + version: 9.26.0 eslint-plugin-prettier: - specifier: ^5.2.6 - version: 5.2.6(eslint@9.25.1)(prettier@3.5.3) + specifier: ^5.4.0 + version: 5.4.0(eslint@9.26.0)(prettier@3.5.3) jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@22.15.3) + version: 29.7.0(@types/node@22.15.14) + joi: + specifier: ^17.13.3 + version: 17.13.3 lemmy-js-client: - specifier: 1.0.0-remove-page-limit.1 - version: 1.0.0-remove-page-limit.1 + specifier: 1.0.0-local-image-user.3 + version: 1.0.0-local-image-user.3 prettier: specifier: ^3.5.3 version: 3.5.3 ts-jest: specifier: ^29.3.2 - version: 29.3.2(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.15.3))(typescript@5.8.3) + version: 29.3.2(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.15.14))(typescript@5.8.3) tsoa: specifier: ^6.6.0 version: 6.6.0 @@ -48,8 +51,8 @@ importers: specifier: ^5.8.3 version: 5.8.3 typescript-eslint: - specifier: ^8.31.0 - version: 8.31.1(eslint@9.25.1)(typescript@5.8.3) + specifier: ^8.32.0 + version: 8.32.0(eslint@9.26.0)(typescript@5.8.3) packages: @@ -230,6 +233,12 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.7.0': + resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -250,8 +259,8 @@ packages: resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.25.1': - resolution: {integrity: sha512-dEIwmjntEx8u3Uvv+kr3PDeeArL8Hw07H9kyYxCjnM9pBjfEhk6uLXSchxxzgiwtRhhzVzqmUSDFBOi1TuZ7qg==} + '@eslint/js@9.26.0': + resolution: {integrity: sha512-I9XlJawFdSMvWjDt6wksMCrgns5ggLNfFwFvnShsleWruvXM514Qxk8V246efTw+eo9JABvVz+u3q2RiAowKxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': @@ -309,6 +318,9 @@ packages: '@hapi/hoek@11.0.7': resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==} + '@hapi/hoek@9.3.0': + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + '@hapi/iron@7.0.1': resolution: {integrity: sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==} @@ -341,6 +353,9 @@ packages: resolution: {integrity: sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==} engines: {node: '>=14.0.0'} + '@hapi/topo@5.1.0': + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + '@hapi/topo@6.0.2': resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} @@ -469,6 +484,10 @@ packages: '@jridgewell/trace-mapping@0.3.22': resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} + '@modelcontextprotocol/sdk@1.11.0': + resolution: {integrity: sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==} + engines: {node: '>=18'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -489,6 +508,15 @@ packages: resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@sideway/address@4.1.5': + resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==} + + '@sideway/formula@3.0.1': + resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==} + + '@sideway/pinpoint@2.0.0': + resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==} + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -582,8 +610,8 @@ packages: '@types/multer@1.4.12': resolution: {integrity: sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==} - '@types/node@22.15.3': - resolution: {integrity: sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==} + '@types/node@22.15.14': + resolution: {integrity: sha512-BL1eyu/XWsFGTtDWOYULQEs4KR0qdtYfCxYAUYRoB7JP7h9ETYLgQTww6kH8Sj2C0pFGgrpM0XKv6/kbIzYJ1g==} '@types/qs@6.9.18': resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} @@ -606,57 +634,61 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@8.31.1': - resolution: {integrity: sha512-oUlH4h1ABavI4F0Xnl8/fOtML/eu8nI2A1nYd+f+55XI0BLu+RIqKoCiZKNo6DtqZBEQm5aNKA20G3Z5w3R6GQ==} + '@typescript-eslint/eslint-plugin@8.32.0': + resolution: {integrity: sha512-/jU9ettcntkBFmWUzzGgsClEi2ZFiikMX5eEQsmxIAWMOn4H3D4rvHssstmAHGVvrYnaMqdWWWg0b5M6IN/MTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.31.1': - resolution: {integrity: sha512-oU/OtYVydhXnumd0BobL9rkJg7wFJ9bFFPmSmB/bf/XWN85hlViji59ko6bSKBXyseT9V8l+CN1nwmlbiN0G7Q==} + '@typescript-eslint/parser@8.32.0': + resolution: {integrity: sha512-B2MdzyWxCE2+SqiZHAjPphft+/2x2FlO9YBx7eKE1BCb+rqBlQdhtAEhzIEdozHd55DXPmxBdpMygFJjfjjA9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.31.1': - resolution: {integrity: sha512-BMNLOElPxrtNQMIsFHE+3P0Yf1z0dJqV9zLdDxN/xLlWMlXK/ApEsVEKzpizg9oal8bAT5Sc7+ocal7AC1HCVw==} + '@typescript-eslint/scope-manager@8.32.0': + resolution: {integrity: sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.31.1': - resolution: {integrity: sha512-fNaT/m9n0+dpSp8G/iOQ05GoHYXbxw81x+yvr7TArTuZuCA6VVKbqWYVZrV5dVagpDTtj/O8k5HBEE/p/HM5LA==} + '@typescript-eslint/type-utils@8.32.0': + resolution: {integrity: sha512-t2vouuYQKEKSLtJaa5bB4jHeha2HJczQ6E5IXPDPgIty9EqcJxpr1QHQ86YyIPwDwxvUmLfP2YADQ5ZY4qddZg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.31.1': - resolution: {integrity: sha512-SfepaEFUDQYRoA70DD9GtytljBePSj17qPxFHA/h3eg6lPTqGJ5mWOtbXCk1YrVU1cTJRd14nhaXWFu0l2troQ==} + '@typescript-eslint/types@8.32.0': + resolution: {integrity: sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.31.1': - resolution: {integrity: sha512-kaA0ueLe2v7KunYOyWYtlf/QhhZb7+qh4Yw6Ni5kgukMIG+iP773tjgBiLWIXYumWCwEq3nLW+TUywEp8uEeag==} + '@typescript-eslint/typescript-estree@8.32.0': + resolution: {integrity: sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.31.1': - resolution: {integrity: sha512-2DSI4SNfF5T4oRveQ4nUrSjUqjMND0nLq9rEkz0gfGr3tg0S5KB6DhwR+WZPCjzkZl3cH+4x2ce3EsL50FubjQ==} + '@typescript-eslint/utils@8.32.0': + resolution: {integrity: sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.31.1': - resolution: {integrity: sha512-I+/rgqOVBn6f0o7NDTmAPWWC6NuqhV174lfYvAm9fUaWeiefLdux9/YI3/nLugEn9L8fcSi0XmpKi/r5u0nmpw==} + '@typescript-eslint/visitor-keys@8.32.0': + resolution: {integrity: sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + accepts@2.0.0: + resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -742,6 +774,10 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@2.2.0: + resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==} + engines: {node: '>=18'} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -838,6 +874,10 @@ packages: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} + content-disposition@1.0.0: + resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==} + engines: {node: '>= 0.6'} + content-type@1.0.5: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} @@ -848,10 +888,22 @@ packages: cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + cookie-signature@1.2.2: + resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==} + engines: {node: '>=6.6.0'} + cookie@0.7.1: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + create-jest@29.7.0: resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -979,8 +1031,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-plugin-prettier@5.2.6: - resolution: {integrity: sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==} + eslint-plugin-prettier@5.4.0: + resolution: {integrity: sha512-BvQOvUhkVQM1i63iMETK9Hjud9QhqBnbtT1Zc642p9ynzBuCe5pybkOnvqZIBypXmMlsGcnU4HZ8sCTPfpAexA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1005,8 +1057,8 @@ packages: resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.25.1: - resolution: {integrity: sha512-E6Mtz9oGQWDCpV12319d59n4tx9zOTXSTmc8BLVxBx+G/0RdM5MvEEJLU9c0+aleoePYYgVTOsRblx433qmhWQ==} + eslint@9.26.0: + resolution: {integrity: sha512-Hx0MOjPh6uK9oq9nVsATZKE/Wlbai7KFjfCuw9UHaguDW3x+HF0O5nIi3ud39TWgrTjTO5nHxmL3R1eANinWHQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -1044,6 +1096,14 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + eventsource-parser@3.0.1: + resolution: {integrity: sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==} + engines: {node: '>=18.0.0'} + + eventsource@3.0.6: + resolution: {integrity: sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==} + engines: {node: '>=18.0.0'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -1056,10 +1116,20 @@ packages: resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + express-rate-limit@7.5.0: + resolution: {integrity: sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==} + engines: {node: '>= 16'} + peerDependencies: + express: ^4.11 || 5 || ^5.0.0-beta.1 + express@4.21.2: resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} engines: {node: '>= 0.10.0'} + express@5.1.0: + resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} + engines: {node: '>= 18'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1101,6 +1171,10 @@ packages: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + finalhandler@2.1.0: + resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==} + engines: {node: '>= 0.8'} + find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -1128,6 +1202,10 @@ packages: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fresh@2.0.0: + resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==} + engines: {node: '>= 0.8'} + fs-extra@11.3.0: resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} engines: {node: '>=14.14'} @@ -1237,6 +1315,10 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1291,6 +1373,9 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-promise@4.0.0: + resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -1463,6 +1548,9 @@ packages: node-notifier: optional: true + joi@17.13.3: + resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1506,8 +1594,8 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - lemmy-js-client@1.0.0-remove-page-limit.1: - resolution: {integrity: sha512-709IESOyQeQ17KfucqO6cf7c3IobEbgwKUdtvcpHhGXKpG3kHYNsMUZR5e7CgbXgSNJ+2OwY8GyhUnNW+TbkZg==} + lemmy-js-client@1.0.0-local-image-user.3: + resolution: {integrity: sha512-h7bW7lZ+8EQzmgk4fSUYo/+3doSx/dlC9rxM4omLKayS/Hwp/pe2TD785RS8ZJUiOtFfX1Ui0P8991N9a50beQ==} leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} @@ -1558,6 +1646,10 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} + media-typer@1.1.0: + resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} + engines: {node: '>= 0.8'} + merge-anything@5.1.7: resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} engines: {node: '>=12.13'} @@ -1565,6 +1657,10 @@ packages: merge-descriptors@1.0.3: resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-descriptors@2.0.0: + resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==} + engines: {node: '>=18'} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -1592,10 +1688,18 @@ packages: resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} engines: {node: '>= 0.6'} + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime-types@3.0.1: + resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} + engines: {node: '>= 0.6'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -1636,6 +1740,10 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -1653,6 +1761,10 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -1729,6 +1841,10 @@ packages: path-to-regexp@0.1.12: resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-to-regexp@8.2.0: + resolution: {integrity: sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==} + engines: {node: '>=16'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1740,6 +1856,10 @@ packages: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} + pkce-challenge@5.0.0: + resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==} + engines: {node: '>=16.20.0'} + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -1780,6 +1900,10 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1791,6 +1915,10 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + raw-body@3.0.0: + resolution: {integrity: sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==} + engines: {node: '>= 0.8'} + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -1825,6 +1953,10 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + router@2.2.0: + resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} + engines: {node: '>= 18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1852,10 +1984,18 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} + send@1.2.0: + resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + engines: {node: '>= 18'} + serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + serve-static@2.2.0: + resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + engines: {node: '>= 18'} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -2044,8 +2184,12 @@ packages: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} - typescript-eslint@8.31.1: - resolution: {integrity: sha512-j6DsEotD/fH39qKzXTQRwYYWlt7D+0HmfpOK+DVhwJOFLcdmn92hq3mBb7HlKJHbjjI/gTOqEcc9d6JfpFf/VA==} + type-is@2.0.1: + resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} + engines: {node: '>= 0.6'} + + typescript-eslint@8.32.0: + resolution: {integrity: sha512-UMq2kxdXCzinFFPsXc9o2ozIpYCCOiEC46MG3yEh5Vipq6BO27otTtEBZA1fQ66DulEUgE97ucQ/3YY66CPg0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -2151,6 +2295,14 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod-to-json-schema@3.24.5: + resolution: {integrity: sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==} + peerDependencies: + zod: ^3.24.1 + + zod@3.24.4: + resolution: {integrity: sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==} + snapshots: '@ampproject/remapping@2.2.1': @@ -2354,9 +2506,14 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@eslint-community/eslint-utils@4.6.1(eslint@9.25.1)': + '@eslint-community/eslint-utils@4.6.1(eslint@9.26.0)': dependencies: - eslint: 9.25.1 + eslint: 9.26.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/eslint-utils@4.7.0(eslint@9.26.0)': + dependencies: + eslint: 9.26.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -2389,7 +2546,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.25.1': {} + '@eslint/js@9.26.0': {} '@eslint/object-schema@2.1.6': {} @@ -2478,6 +2635,8 @@ snapshots: '@hapi/hoek@11.0.7': {} + '@hapi/hoek@9.3.0': {} + '@hapi/iron@7.0.1': dependencies: '@hapi/b64': 6.0.1 @@ -2542,6 +2701,10 @@ snapshots: '@hapi/teamwork@6.0.0': {} + '@hapi/topo@5.1.0': + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo@6.0.2': dependencies: '@hapi/hoek': 11.0.7 @@ -2596,7 +2759,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -2609,14 +2772,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.15.3) + jest-config: 29.7.0(@types/node@22.15.14) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -2641,7 +2804,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -2659,7 +2822,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.15.3 + '@types/node': 22.15.14 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2681,7 +2844,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.22 - '@types/node': 22.15.3 + '@types/node': 22.15.14 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -2751,7 +2914,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -2772,6 +2935,21 @@ snapshots: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 + '@modelcontextprotocol/sdk@1.11.0': + dependencies: + content-type: 1.0.5 + cors: 2.8.5 + cross-spawn: 7.0.6 + eventsource: 3.0.6 + express: 5.1.0 + express-rate-limit: 7.5.0(express@5.1.0) + pkce-challenge: 5.0.0 + raw-body: 3.0.0 + zod: 3.24.4 + zod-to-json-schema: 3.24.5(zod@3.24.4) + transitivePeerDependencies: + - supports-color + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2789,6 +2967,14 @@ snapshots: '@pkgr/core@0.2.4': {} + '@sideway/address@4.1.5': + dependencies: + '@hapi/hoek': 9.3.0 + + '@sideway/formula@3.0.1': {} + + '@sideway/pinpoint@2.0.0': {} + '@sinclair/typebox@0.27.8': {} '@sinonjs/commons@3.0.1': @@ -2830,7 +3016,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/babel__core@7.20.5': dependencies: @@ -2856,11 +3042,11 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/connect@3.4.38': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/content-disposition@0.5.8': {} @@ -2869,13 +3055,13 @@ snapshots: '@types/connect': 3.4.38 '@types/express': 5.0.0 '@types/keygrip': 1.0.6 - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/estree@1.0.7': {} '@types/express-serve-static-core@5.0.6': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/qs': 6.9.18 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -2889,7 +3075,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/http-assert@1.5.6': {} @@ -2927,7 +3113,7 @@ snapshots: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/mime@1.3.5': {} @@ -2935,7 +3121,7 @@ snapshots: dependencies: '@types/express': 5.0.0 - '@types/node@22.15.3': + '@types/node@22.15.14': dependencies: undici-types: 6.21.0 @@ -2946,12 +3132,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 22.15.3 + '@types/node': 22.15.14 '@types/send': 0.17.4 '@types/stack-utils@2.0.3': {} @@ -2962,15 +3148,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.31.1(eslint@9.25.1)(typescript@5.8.3) - '@typescript-eslint/scope-manager': 8.31.1 - '@typescript-eslint/type-utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) - '@typescript-eslint/utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.31.1 - eslint: 9.25.1 + '@typescript-eslint/parser': 8.32.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/scope-manager': 8.32.0 + '@typescript-eslint/type-utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.32.0 + eslint: 9.26.0 graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -2979,40 +3165,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3)': + '@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3)': dependencies: - '@typescript-eslint/scope-manager': 8.31.1 - '@typescript-eslint/types': 8.31.1 - '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3) - '@typescript-eslint/visitor-keys': 8.31.1 + '@typescript-eslint/scope-manager': 8.32.0 + '@typescript-eslint/types': 8.32.0 + '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3) + '@typescript-eslint/visitor-keys': 8.32.0 debug: 4.4.0 - eslint: 9.25.1 + eslint: 9.26.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.31.1': + '@typescript-eslint/scope-manager@8.32.0': dependencies: - '@typescript-eslint/types': 8.31.1 - '@typescript-eslint/visitor-keys': 8.31.1 + '@typescript-eslint/types': 8.32.0 + '@typescript-eslint/visitor-keys': 8.32.0 - '@typescript-eslint/type-utils@8.31.1(eslint@9.25.1)(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.32.0(eslint@9.26.0)(typescript@5.8.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3) - '@typescript-eslint/utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) + '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3) debug: 4.4.0 - eslint: 9.25.1 + eslint: 9.26.0 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.31.1': {} + '@typescript-eslint/types@8.32.0': {} - '@typescript-eslint/typescript-estree@8.31.1(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.32.0(typescript@5.8.3)': dependencies: - '@typescript-eslint/types': 8.31.1 - '@typescript-eslint/visitor-keys': 8.31.1 + '@typescript-eslint/types': 8.32.0 + '@typescript-eslint/visitor-keys': 8.32.0 debug: 4.4.0 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -3023,20 +3209,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.31.1(eslint@9.25.1)(typescript@5.8.3)': + '@typescript-eslint/utils@8.32.0(eslint@9.26.0)(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1) - '@typescript-eslint/scope-manager': 8.31.1 - '@typescript-eslint/types': 8.31.1 - '@typescript-eslint/typescript-estree': 8.31.1(typescript@5.8.3) - eslint: 9.25.1 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0) + '@typescript-eslint/scope-manager': 8.32.0 + '@typescript-eslint/types': 8.32.0 + '@typescript-eslint/typescript-estree': 8.32.0(typescript@5.8.3) + eslint: 9.26.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.31.1': + '@typescript-eslint/visitor-keys@8.32.0': dependencies: - '@typescript-eslint/types': 8.31.1 + '@typescript-eslint/types': 8.32.0 eslint-visitor-keys: 4.2.0 accepts@1.3.8: @@ -3044,6 +3230,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + accepts@2.0.0: + dependencies: + mime-types: 3.0.1 + negotiator: 1.0.0 + acorn-jsx@5.3.2(acorn@8.14.1): dependencies: acorn: 8.14.1 @@ -3159,6 +3350,20 @@ snapshots: transitivePeerDependencies: - supports-color + body-parser@2.2.0: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 4.4.0 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + on-finished: 2.4.1 + qs: 6.14.0 + raw-body: 3.0.0 + type-is: 2.0.1 + transitivePeerDependencies: + - supports-color + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -3246,21 +3451,34 @@ snapshots: dependencies: safe-buffer: 5.2.1 + content-disposition@1.0.0: + dependencies: + safe-buffer: 5.2.1 + content-type@1.0.5: {} convert-source-map@2.0.0: {} cookie-signature@1.0.6: {} + cookie-signature@1.2.2: {} + cookie@0.7.1: {} - create-jest@29.7.0(@types/node@22.15.3): + cookie@0.7.2: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + create-jest@29.7.0(@types/node@22.15.14): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.15.3) + jest-config: 29.7.0(@types/node@22.15.14) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3349,9 +3567,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-prettier@5.2.6(eslint@9.25.1)(prettier@3.5.3): + eslint-plugin-prettier@5.4.0(eslint@9.26.0)(prettier@3.5.3): dependencies: - eslint: 9.25.1 + eslint: 9.26.0 prettier: 3.5.3 prettier-linter-helpers: 1.0.0 synckit: 0.11.4 @@ -3365,19 +3583,20 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.25.1: + eslint@9.26.0: dependencies: - '@eslint-community/eslint-utils': 4.6.1(eslint@9.25.1) + '@eslint-community/eslint-utils': 4.6.1(eslint@9.26.0) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.20.0 '@eslint/config-helpers': 0.2.1 '@eslint/core': 0.13.0 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.25.1 + '@eslint/js': 9.26.0 '@eslint/plugin-kit': 0.2.8 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.2 + '@modelcontextprotocol/sdk': 1.11.0 '@types/estree': 1.0.7 '@types/json-schema': 7.0.15 ajv: 6.12.6 @@ -3402,6 +3621,7 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + zod: 3.24.4 transitivePeerDependencies: - supports-color @@ -3427,6 +3647,12 @@ snapshots: etag@1.8.1: {} + eventsource-parser@3.0.1: {} + + eventsource@3.0.6: + dependencies: + eventsource-parser: 3.0.1 + execa@5.1.1: dependencies: cross-spawn: 7.0.3 @@ -3449,6 +3675,10 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 + express-rate-limit@7.5.0(express@5.1.0): + dependencies: + express: 5.1.0 + express@4.21.2: dependencies: accepts: 1.3.8 @@ -3485,6 +3715,38 @@ snapshots: transitivePeerDependencies: - supports-color + express@5.1.0: + dependencies: + accepts: 2.0.0 + body-parser: 2.2.0 + content-disposition: 1.0.0 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.2.2 + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 2.1.0 + fresh: 2.0.0 + http-errors: 2.0.0 + merge-descriptors: 2.0.0 + mime-types: 3.0.1 + on-finished: 2.4.1 + once: 1.4.0 + parseurl: 1.3.3 + proxy-addr: 2.0.7 + qs: 6.14.0 + range-parser: 1.2.1 + router: 2.2.0 + send: 1.2.0 + serve-static: 2.2.0 + statuses: 2.0.1 + type-is: 2.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -3537,6 +3799,17 @@ snapshots: transitivePeerDependencies: - supports-color + finalhandler@2.1.0: + dependencies: + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -3563,6 +3836,8 @@ snapshots: fresh@0.5.2: {} + fresh@2.0.0: {} + fs-extra@11.3.0: dependencies: graceful-fs: 4.2.11 @@ -3675,6 +3950,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + ignore@5.3.2: {} import-fresh@3.3.1: @@ -3716,6 +3995,8 @@ snapshots: is-number@7.0.0: {} + is-promise@4.0.0: {} + is-stream@2.0.1: {} is-what@4.1.16: {} @@ -3788,7 +4069,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -3808,16 +4089,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.15.3): + jest-cli@29.7.0(@types/node@22.15.14): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.15.3) + create-jest: 29.7.0(@types/node@22.15.14) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@22.15.3) + jest-config: 29.7.0(@types/node@22.15.14) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -3827,7 +4108,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.15.3): + jest-config@29.7.0(@types/node@22.15.14): dependencies: '@babel/core': 7.23.9 '@jest/test-sequencer': 29.7.0 @@ -3852,7 +4133,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.14 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -3881,7 +4162,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3891,7 +4172,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.15.3 + '@types/node': 22.15.14 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -3930,7 +4211,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -3965,7 +4246,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -3993,7 +4274,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -4039,7 +4320,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -4058,7 +4339,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.3 + '@types/node': 22.15.14 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -4067,23 +4348,31 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.15.3 + '@types/node': 22.15.14 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.15.3): + jest@29.7.0(@types/node@22.15.14): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@22.15.3) + jest-cli: 29.7.0(@types/node@22.15.14) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - supports-color - ts-node + joi@17.13.3: + dependencies: + '@hapi/hoek': 9.3.0 + '@hapi/topo': 5.1.0 + '@sideway/address': 4.1.5 + '@sideway/formula': 3.0.1 + '@sideway/pinpoint': 2.0.0 + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -4119,7 +4408,7 @@ snapshots: kleur@3.0.3: {} - lemmy-js-client@1.0.0-remove-page-limit.1: + lemmy-js-client@1.0.0-local-image-user.3: dependencies: '@tsoa/runtime': 6.6.0 transitivePeerDependencies: @@ -4166,12 +4455,16 @@ snapshots: media-typer@0.3.0: {} + media-typer@1.1.0: {} + merge-anything@5.1.7: dependencies: is-what: 4.1.16 merge-descriptors@1.0.3: {} + merge-descriptors@2.0.0: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} @@ -4192,10 +4485,16 @@ snapshots: mime-db@1.53.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 + mime-types@3.0.1: + dependencies: + mime-db: 1.54.0 + mime@1.6.0: {} mimic-fn@2.1.0: {} @@ -4224,6 +4523,8 @@ snapshots: negotiator@0.6.3: {} + negotiator@1.0.0: {} + neo-async@2.6.2: {} node-int64@0.4.0: {} @@ -4236,6 +4537,8 @@ snapshots: dependencies: path-key: 3.1.1 + object-assign@4.1.1: {} + object-inspect@1.13.4: {} on-finished@2.4.1: @@ -4307,12 +4610,16 @@ snapshots: path-to-regexp@0.1.12: {} + path-to-regexp@8.2.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} pirates@4.0.6: {} + pkce-challenge@5.0.0: {} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -4349,6 +4656,10 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + queue-microtask@1.2.3: {} range-parser@1.2.1: {} @@ -4360,6 +4671,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + raw-body@3.0.0: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.6.3 + unpipe: 1.0.0 + react-is@18.3.1: {} reflect-metadata@0.2.2: {} @@ -4384,6 +4702,16 @@ snapshots: reusify@1.1.0: {} + router@2.2.0: + dependencies: + debug: 4.4.0 + depd: 2.0.0 + is-promise: 4.0.0 + parseurl: 1.3.3 + path-to-regexp: 8.2.0 + transitivePeerDependencies: + - supports-color + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -4416,6 +4744,22 @@ snapshots: transitivePeerDependencies: - supports-color + send@1.2.0: + dependencies: + debug: 4.4.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 2.0.0 + http-errors: 2.0.0 + mime-types: 3.0.1 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + serve-static@1.16.2: dependencies: encodeurl: 2.0.0 @@ -4425,6 +4769,15 @@ snapshots: transitivePeerDependencies: - supports-color + serve-static@2.2.0: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 1.2.0 + transitivePeerDependencies: + - supports-color + setprototypeof@1.2.0: {} shebang-command@2.0.0: @@ -4552,12 +4905,12 @@ snapshots: ts-deepmerge@7.0.2: {} - ts-jest@29.3.2(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.15.3))(typescript@5.8.3): + ts-jest@29.3.2(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.15.14))(typescript@5.8.3): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.15.3) + jest: 29.7.0(@types/node@22.15.14) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -4596,12 +4949,18 @@ snapshots: media-typer: 0.3.0 mime-types: 2.1.35 - typescript-eslint@8.31.1(eslint@9.25.1)(typescript@5.8.3): + type-is@2.0.1: dependencies: - '@typescript-eslint/eslint-plugin': 8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.25.1)(typescript@5.8.3))(eslint@9.25.1)(typescript@5.8.3) - '@typescript-eslint/parser': 8.31.1(eslint@9.25.1)(typescript@5.8.3) - '@typescript-eslint/utils': 8.31.1(eslint@9.25.1)(typescript@5.8.3) - eslint: 9.25.1 + content-type: 1.0.5 + media-typer: 1.1.0 + mime-types: 3.0.1 + + typescript-eslint@8.32.0(eslint@9.26.0)(typescript@5.8.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.32.0(@typescript-eslint/parser@8.32.0(eslint@9.26.0)(typescript@5.8.3))(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.32.0(eslint@9.26.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.32.0(eslint@9.26.0)(typescript@5.8.3) + eslint: 9.26.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color @@ -4689,3 +5048,9 @@ snapshots: yargs-parser: 21.1.1 yocto-queue@0.1.0: {} + + zod-to-json-schema@3.24.5(zod@3.24.4): + dependencies: + zod: 3.24.4 + + zod@3.24.4: {} diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index c45491ee9..1bd0caa5c 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -3,8 +3,7 @@ # it is expected that this script is called by run-federation-test.sh script. set -e -if [ -z "$LEMMY_LOG_LEVEL" ]; -then +if [ -z "$LEMMY_LOG_LEVEL" ]; then LEMMY_LOG_LEVEL=info fi @@ -16,11 +15,10 @@ export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queu PICTRS_PATH="api_tests/pict-rs" PICTRS_EXPECTED_HASH="7f7ac2a45ef9b13403ee139b7512135be6b060ff2f6460e0c800e18e1b49d2fd api_tests/pict-rs" -# Pictrs setup. Download file with hash check and up to 3 retries. +# Pictrs setup. Download file with hash check and up to 3 retries. if [ ! -f "$PICTRS_PATH" ]; then count=0 - while [ ! -f "$PICTRS_PATH" ] && [ "$count" -lt 3 ] - do + while [ ! -f "$PICTRS_PATH" ] && [ "$count" -lt 3 ]; do # This one sometimes goes down curl "https://git.asonix.dog/asonix/pict-rs/releases/download/v0.5.17-pre.9/pict-rs-linux-amd64" -o "$PICTRS_PATH" # curl "https://codeberg.org/asonix/pict-rs/releases/download/v0.5.5/pict-rs-linux-amd64" -o "$PICTRS_PATH" diff --git a/api_tests/src/comment.spec.ts b/api_tests/src/comment.spec.ts index 853427d26..ab7320fae 100644 --- a/api_tests/src/comment.spec.ts +++ b/api_tests/src/comment.spec.ts @@ -54,7 +54,7 @@ let postOnAlphaRes: PostResponse; beforeAll(async () => { await setupLogins(); - await Promise.all([followBeta(alpha), followBeta(gamma)]); + await Promise.allSettled([followBeta(alpha), followBeta(gamma)]); betaCommunity = (await resolveBetaCommunity(alpha)).community; if (betaCommunity) { postOnAlphaRes = await createPost(alpha, betaCommunity.community.id); @@ -705,7 +705,7 @@ test("Check that activity from another instance is sent to third instance", asyn commentRes.comment_view, ); - await Promise.all([unfollowRemotes(alpha), unfollowRemotes(gamma)]); + await Promise.allSettled([unfollowRemotes(alpha), unfollowRemotes(gamma)]); }); test("Fetch in_reply_tos: A is unsubbed from B, B makes a post, and some embedded comments, A subs to B, B updates the lowest level comment, A fetches both the post and all the inreplyto comments for that post.", async () => { diff --git a/api_tests/src/image.spec.ts b/api_tests/src/image.spec.ts index 4a715c824..fcbcb08ea 100644 --- a/api_tests/src/image.spec.ts +++ b/api_tests/src/image.spec.ts @@ -37,16 +37,13 @@ import { beforeAll(setupLogins); afterAll(async () => { - await Promise.all([unfollows(), deleteAllMedia(alpha)]); + await Promise.allSettled([unfollows(), deleteAllMedia(alpha)]); }); test("Upload image and delete it", async () => { const health = await alpha.imageHealth(); expect(health.success).toBeTruthy(); - // Before running this test, you need to delete all previous images in the DB - await deleteAllMedia(alpha); - // Upload test image. We use a simple string buffer as pictrs doesn't require an actual image // in testing mode. const upload_form: UploadImage = { diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index b1fa06060..d93453cc8 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -462,7 +462,7 @@ test("Search for a post", async () => { expect(betaPost?.post.name).toBeDefined(); }); -test.only("Enforce site ban federation for local user", async () => { +test("Enforce site ban federation for local user", async () => { if (!betaCommunity) { throw "Missing beta community"; } diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 0998e47c1..5dd525e86 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -768,7 +768,7 @@ export async function unfollowRemotes(api: LemmyHttp): Promise { let my_user = await getMyUser(api); let remoteFollowed = my_user.follows.filter(c => c.community.local == false) ?? []; - await Promise.all( + await Promise.allSettled( remoteFollowed.map(cu => followCommunity(api, false, cu.community.id)), ); @@ -930,7 +930,7 @@ export async function deleteAllMedia(api: LemmyHttp) { const imagesRes = await api.listMediaAdmin({ limit: imageFetchLimit, }); - Promise.all( + Promise.allSettled( imagesRes.images .map(image => { const form: DeleteImageParams = { @@ -943,14 +943,14 @@ export async function deleteAllMedia(api: LemmyHttp) { } export async function unfollows() { - await Promise.all([ + await Promise.allSettled([ unfollowRemotes(alpha), unfollowRemotes(beta), unfollowRemotes(gamma), unfollowRemotes(delta), unfollowRemotes(epsilon), ]); - await Promise.all([ + await Promise.allSettled([ purgeAllPosts(alpha), purgeAllPosts(beta), purgeAllPosts(gamma), @@ -962,7 +962,7 @@ export async function unfollows() { export async function purgeAllPosts(api: LemmyHttp) { // The best way to get all federated items, is to find the posts let res = await api.getPosts({ type_: "All", limit: 50 }); - await Promise.all( + await Promise.allSettled( Array.from(new Set(res.posts.map(p => p.post.id))) .map(post_id => api.purgePost({ post_id })) // Ignore errors diff --git a/crates/api/src/local_user/list_media.rs b/crates/api/src/local_user/list_media.rs index 12300818b..a537f538a 100644 --- a/crates/api/src/local_user/list_media.rs +++ b/crates/api/src/local_user/list_media.rs @@ -19,9 +19,9 @@ pub async fn list_media( None }; - let images = LocalImageView::get_all_paged_by_local_user_id( + let images = LocalImageView::get_all_paged_by_person_id( &mut context.pool(), - local_user_view.local_user.id, + local_user_view.person.id, cursor_data, data.page_back, data.limit, diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index 08cf1c137..9b59b1055 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -219,7 +219,7 @@ pub async fn generate_post_link_metadata( }; let image_url = if is_image_post { - post.url + post.url.clone() } else { metadata.opengraph_data.image.clone() }; @@ -233,7 +233,7 @@ pub async fn generate_post_link_metadata( .ok() .or(Some(url.into())) } else if let (true, Some(url)) = (allow_generate_thumbnail, image_url.clone()) { - generate_pictrs_thumbnail(&url, &context) + generate_pictrs_thumbnail(&post, &url, &context) .await .map_err(|e| warn!("Failed to generate thumbnail: {e}")) .ok() @@ -443,7 +443,11 @@ pub async fn delete_image_from_pictrs(alias: &str, context: &LemmyContext) -> Le } /// Retrieves the image with local pict-rs and generates a thumbnail. Returns the thumbnail url. -async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> LemmyResult { +async fn generate_pictrs_thumbnail( + post: &Post, + image_url: &Url, + context: &LemmyContext, +) -> LemmyResult { let pictrs_config = context.settings().pictrs()?; match pictrs_config.image_mode { @@ -482,10 +486,10 @@ async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> L .ok_or(LemmyErrorType::PictrsResponseError(res.msg))?; let form = LocalImageForm { - // This is none because its an internal request. - // IE, a local user shouldn't get to delete the thumbnails for their link posts - local_user_id: None, pictrs_alias: image.file.clone(), + // For thumbnails, the person_id is the post creator + person_id: post.creator_id, + thumbnail_for_post_id: Some(Some(post.id)), }; let protocol_and_hostname = context.settings().get_protocol_and_hostname(); let thumbnail_url = image.image_url(&protocol_and_hostname)?; diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index fe9f1e25c..bb47b286a 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -549,19 +549,15 @@ pub async fn purge_post_images( } } -/// Delete a local_user's images +/// Delete local images attributed to a person async fn delete_local_user_images(person_id: PersonId, context: &LemmyContext) -> LemmyResult<()> { - if let Ok(local_user) = LocalUserView::read_person(&mut context.pool(), person_id).await { - let pictrs_uploads = - LocalImageView::get_all_by_local_user_id(&mut context.pool(), local_user.local_user.id) - .await?; + let pictrs_uploads = LocalImageView::get_all_by_person_id(&mut context.pool(), person_id).await?; - // Delete their images - for upload in pictrs_uploads { - delete_image_from_pictrs(&upload.local_image.pictrs_alias, context) - .await - .ok(); - } + // Delete their images + for upload in pictrs_uploads { + delete_image_from_pictrs(&upload.local_image.pictrs_alias, context) + .await + .ok(); } Ok(()) } diff --git a/crates/db_schema/src/impls/images.rs b/crates/db_schema/src/impls/images.rs index 45db1f147..7f442359d 100644 --- a/crates/db_schema/src/impls/images.rs +++ b/crates/db_schema/src/impls/images.rs @@ -1,5 +1,5 @@ use crate::{ - newtypes::{DbUrl, LocalUserId}, + newtypes::{DbUrl, PersonId}, source::images::{ImageDetails, ImageDetailsInsertForm, LocalImage, LocalImageForm, RemoteImage}, utils::{get_conn, DbPool}, }; @@ -65,14 +65,14 @@ impl LocalImage { pub async fn delete_by_alias_and_user( pool: &mut DbPool<'_>, alias: &str, - local_user_id: LocalUserId, + person_id: PersonId, ) -> LemmyResult { let conn = &mut get_conn(pool).await?; diesel::delete( local_image::table.filter( local_image::pictrs_alias .eq(alias) - .and(local_image::local_user_id.eq(local_user_id)), + .and(local_image::person_id.eq(person_id)), ), ) .get_result(conn) diff --git a/crates/db_schema/src/source/images.rs b/crates/db_schema/src/source/images.rs index 33ea44ea4..4ccb4c378 100644 --- a/crates/db_schema/src/source/images.rs +++ b/crates/db_schema/src/source/images.rs @@ -1,4 +1,4 @@ -use crate::newtypes::{DbUrl, LocalUserId}; +use crate::newtypes::{DbUrl, PersonId, PostId}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; @@ -25,26 +25,26 @@ use { )] #[cfg_attr(feature = "full", ts(export))] #[cfg_attr(feature = "full", diesel(table_name = local_image))] -#[cfg_attr( - feature = "full", - diesel(belongs_to(crate::source::local_user::LocalUser)) -)] +#[cfg_attr(feature = "full", diesel(belongs_to(crate::source::person::Person)))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] #[cfg_attr(feature = "full", diesel(primary_key(pictrs_alias)))] #[cfg_attr(feature = "full", cursor_keys_module(name = local_image_keys))] pub struct LocalImage { - #[cfg_attr(feature = "full", ts(optional))] - pub local_user_id: Option, pub pictrs_alias: String, pub published: DateTime, + pub person_id: PersonId, + #[cfg_attr(feature = "full", ts(optional))] + /// This means the image is an auto-generated thumbnail, for a post. + pub thumbnail_for_post_id: Option, } #[derive(Debug, Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = local_image))] pub struct LocalImageForm { - pub local_user_id: Option, pub pictrs_alias: String, + pub person_id: PersonId, + pub thumbnail_for_post_id: Option>, } /// Stores all images which are hosted on remote domains. When attempting to proxy an image, it diff --git a/crates/db_schema_file/src/schema.rs b/crates/db_schema_file/src/schema.rs index df2b215ef..d6baacdae 100644 --- a/crates/db_schema_file/src/schema.rs +++ b/crates/db_schema_file/src/schema.rs @@ -393,9 +393,10 @@ diesel::table! { diesel::table! { local_image (pictrs_alias) { - local_user_id -> Nullable, pictrs_alias -> Text, published -> Timestamptz, + person_id -> Int4, + thumbnail_for_post_id -> Nullable, } } @@ -1117,7 +1118,8 @@ diesel::joinable!(inbox_combined -> person_post_mention (person_post_mention_id) diesel::joinable!(inbox_combined -> private_message (private_message_id)); diesel::joinable!(instance_actions -> instance (instance_id)); diesel::joinable!(instance_actions -> person (person_id)); -diesel::joinable!(local_image -> local_user (local_user_id)); +diesel::joinable!(local_image -> person (person_id)); +diesel::joinable!(local_image -> post (thumbnail_for_post_id)); diesel::joinable!(local_site -> site (site_id)); diesel::joinable!(local_site_rate_limit -> local_site (local_site_id)); diesel::joinable!(local_user -> person (person_id)); diff --git a/crates/db_views/local_image/src/impls.rs b/crates/db_views/local_image/src/impls.rs index e8458bf80..b03db0f9c 100644 --- a/crates/db_views/local_image/src/impls.rs +++ b/crates/db_views/local_image/src/impls.rs @@ -1,27 +1,27 @@ use crate::LocalImageView; -use diesel::{ExpressionMethods, JoinOnDsl, QueryDsl, SelectableHelper}; +use diesel::{ExpressionMethods, QueryDsl, SelectableHelper}; use diesel_async::RunQueryDsl; use i_love_jesus::SortDirection; use lemmy_db_schema::{ - newtypes::{LocalUserId, PaginationCursor}, + newtypes::{PaginationCursor, PersonId}, source::images::{local_image_keys as key, LocalImage}, traits::PaginationCursorBuilder, utils::{get_conn, limit_fetch, paginate, DbPool}, }; -use lemmy_db_schema_file::schema::{local_image, local_user, person}; +use lemmy_db_schema_file::schema::{local_image, person, post}; use lemmy_utils::error::{LemmyErrorExt, LemmyErrorType, LemmyResult}; impl LocalImageView { #[diesel::dsl::auto_type(no_type_alias)] fn joins() -> _ { local_image::table - .inner_join(local_user::table) - .inner_join(person::table.on(local_user::person_id.eq(person::id))) + .inner_join(person::table) + .left_join(post::table) } - pub async fn get_all_paged_by_local_user_id( + pub async fn get_all_paged_by_person_id( pool: &mut DbPool<'_>, - user_id: LocalUserId, + person_id: PersonId, cursor_data: Option, page_back: Option, limit: Option, @@ -30,7 +30,7 @@ impl LocalImageView { let limit = limit_fetch(limit)?; let query = Self::joins() - .filter(local_image::local_user_id.eq(user_id)) + .filter(local_image::person_id.eq(person_id)) .select(Self::as_select()) .limit(limit) .into_boxed(); @@ -44,13 +44,13 @@ impl LocalImageView { .with_lemmy_type(LemmyErrorType::NotFound) } - pub async fn get_all_by_local_user_id( + pub async fn get_all_by_person_id( pool: &mut DbPool<'_>, - user_id: LocalUserId, + person_id: PersonId, ) -> LemmyResult> { let conn = &mut get_conn(pool).await?; Self::joins() - .filter(local_image::local_user_id.eq(user_id)) + .filter(local_image::person_id.eq(person_id)) .select(Self::as_select()) .load::(conn) .await diff --git a/crates/db_views/local_image/src/lib.rs b/crates/db_views/local_image/src/lib.rs index b7f787980..035d64696 100644 --- a/crates/db_views/local_image/src/lib.rs +++ b/crates/db_views/local_image/src/lib.rs @@ -1,4 +1,4 @@ -use lemmy_db_schema::source::{images::LocalImage, person::Person}; +use lemmy_db_schema::source::{images::LocalImage, person::Person, post::Post}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] @@ -21,4 +21,7 @@ pub struct LocalImageView { pub local_image: LocalImage, #[cfg_attr(feature = "full", diesel(embed))] pub person: Person, + #[cfg_attr(feature = "full", diesel(embed))] + #[cfg_attr(feature = "full", ts(optional))] + pub post: Option, } diff --git a/crates/routes/src/images/delete.rs b/crates/routes/src/images/delete.rs index 7230ce535..410224a43 100644 --- a/crates/routes/src/images/delete.rs +++ b/crates/routes/src/images/delete.rs @@ -131,7 +131,7 @@ pub async fn delete_image( LocalImage::delete_by_alias_and_user( &mut context.pool(), &data.filename, - local_user_view.local_user.id, + local_user_view.person.id, ) .await?; diff --git a/crates/routes/src/images/upload.rs b/crates/routes/src/images/upload.rs index 334f5b891..f07080f08 100644 --- a/crates/routes/src/images/upload.rs +++ b/crates/routes/src/images/upload.rs @@ -221,8 +221,9 @@ pub async fn do_upload_image( // but still a user may upload multiple and so we need to store all links in db for // to allow deletion via web ui. let form = LocalImageForm { - local_user_id: Some(local_user_view.local_user.id), pictrs_alias: image.file.to_string(), + person_id: local_user_view.person.id, + thumbnail_for_post_id: None, }; let protocol_and_hostname = context.settings().get_protocol_and_hostname(); diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 68f07bc54..c1a67ab72 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -66,7 +66,7 @@ services: # entrypoint: /sbin/tini -- /usr/local/bin/pict-rs -p /mnt -m 4 --image-format webp environment: - PICTRS_OPENTELEMETRY_URL=http://otel:4137 - - PICTRS__API_KEY=API_KEY + - PICTRS__SERVER__API_KEY=my-pictrs-key - PICTRS__MEDIA__VIDEO_CODEC=vp9 - PICTRS__MEDIA__GIF__MAX_WIDTH=256 - PICTRS__MEDIA__GIF__MAX_HEIGHT=256 diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 7148216ad..99d401726 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -53,6 +53,8 @@ services: user: 991:991 volumes: - ./volumes/pictrs_alpha:/mnt:Z + environment: + - PICTRS__SERVER__API_KEY=my-pictrs-key lemmy-alpha-ui: <<: *ui-default diff --git a/docker/federation/lemmy_delta.hjson b/docker/federation/lemmy_delta.hjson index acfddc304..ba2a32218 100644 --- a/docker/federation/lemmy_delta.hjson +++ b/docker/federation/lemmy_delta.hjson @@ -10,4 +10,8 @@ database: { connection: "postgres://lemmy:password@postgres_delta:5432/lemmy" } + pictrs: { + api_key: "my-pictrs-key" + image_mode: StoreLinkPreviews + } } diff --git a/docker/lemmy.hjson b/docker/lemmy.hjson index e28a49b6d..ae2ce2a35 100644 --- a/docker/lemmy.hjson +++ b/docker/lemmy.hjson @@ -20,7 +20,7 @@ pictrs: { url: "http://pictrs:8080/" - # api_key: "API_KEY" + api_key: "my-pictrs-key" image_mode: None } diff --git a/migrations/2025-05-06-145536_local_image_person/down.sql b/migrations/2025-05-06-145536_local_image_person/down.sql new file mode 100644 index 000000000..f76b0e625 --- /dev/null +++ b/migrations/2025-05-06-145536_local_image_person/down.sql @@ -0,0 +1,46 @@ +ALTER TABLE local_image + ADD COLUMN local_user_id int REFERENCES local_user (id) ON UPDATE CASCADE ON DELETE CASCADE; + +UPDATE + local_image AS li +SET + local_user_id = lu.id +FROM + local_user AS lu +WHERE + li.person_id = lu.person_id; + +-- You need to have the exact correct column order, so this needs to be re-created +-- +-- Rename the table +ALTER TABLE local_image RENAME TO local_image_old; + +-- Rename a few constraints +ALTER TABLE local_image_old RENAME CONSTRAINT image_upload_pkey TO image_upload_pkey_old; + +-- Create the old one again +CREATE TABLE local_image ( + local_user_id integer, + pictrs_alias text NOT NULL, + published timestamp with time zone DEFAULT now() NOT NULL +); + +ALTER TABLE ONLY local_image + ADD CONSTRAINT image_upload_pkey PRIMARY KEY (pictrs_alias); + +CREATE INDEX idx_image_upload_local_user_id ON local_image USING btree (local_user_id); + +ALTER TABLE ONLY local_image + ADD CONSTRAINT image_upload_local_user_id_fkey FOREIGN KEY (local_user_id) REFERENCES local_user (id) ON UPDATE CASCADE ON DELETE CASCADE; + +-- Insert the data again +INSERT INTO local_image (local_user_id, pictrs_alias, published) +SELECT + local_user_id, + pictrs_alias, + published +FROM + local_image_old; + +DROP TABLE local_image_old; + diff --git a/migrations/2025-05-06-145536_local_image_person/up.sql b/migrations/2025-05-06-145536_local_image_person/up.sql new file mode 100644 index 000000000..9cde9f3a4 --- /dev/null +++ b/migrations/2025-05-06-145536_local_image_person/up.sql @@ -0,0 +1,31 @@ +-- Since local thumbnails could be generated from posts of external users, +-- use the person_id instead of local_user_id for the LocalImage table. +-- +-- Also connect the thumbnail to a post id. +-- +-- See https://github.com/LemmyNet/lemmy/issues/5564 +ALTER TABLE local_image + ADD COLUMN person_id int NOT NULL DEFAULT 0 REFERENCES person (id) ON UPDATE CASCADE ON DELETE CASCADE, + ADD COLUMN thumbnail_for_post_id int REFERENCES post (id) ON UPDATE CASCADE ON DELETE CASCADE; + +-- Update historical person_id columns +-- Note: The local_user_id rows are null for thumbnails, so there's nothing you can do there. +UPDATE + local_image AS li +SET + person_id = lu.person_id +FROM + local_user AS lu +WHERE + li.local_user_id = lu.id; + +-- Remove the default +ALTER TABLE local_image + ALTER COLUMN person_id DROP DEFAULT; + +-- Remove the local_user_id column +ALTER TABLE local_image + DROP COLUMN local_user_id; + +CREATE INDEX idx_image_upload_person_id ON local_image (person_id); +