diff --git a/package-lock.json b/package-lock.json index b004d4483c279582f5a2c07f3451106462dc7e6c..cef9c39aeff7cd1a2ea72710729069817adb943e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -92,14 +92,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "devOptional": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -497,18 +497,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "devOptional": true, "engines": { "node": ">=6.9.0" @@ -538,25 +538,25 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "dev": true, "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "dev": true, "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -2145,25 +2145,22 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", - "integrity": "sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2211,13 +2208,13 @@ "dev": true }, "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2261,9 +2258,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", - "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", + "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", "cpu": [ "ppc64" ], @@ -2277,9 +2274,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", - "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", + "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", "cpu": [ "arm" ], @@ -2293,9 +2290,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", - "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", + "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", "cpu": [ "arm64" ], @@ -2309,9 +2306,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", - "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", + "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", "cpu": [ "x64" ], @@ -2325,9 +2322,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", - "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", + "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", "cpu": [ "arm64" ], @@ -2341,9 +2338,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", - "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", + "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", "cpu": [ "x64" ], @@ -2357,9 +2354,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", - "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", + "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", "cpu": [ "arm64" ], @@ -2373,9 +2370,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", - "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", + "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", "cpu": [ "x64" ], @@ -2389,9 +2386,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", - "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", + "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", "cpu": [ "arm" ], @@ -2405,9 +2402,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", - "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", + "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", "cpu": [ "arm64" ], @@ -2421,9 +2418,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", - "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", + "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", "cpu": [ "ia32" ], @@ -2437,9 +2434,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", - "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", + "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", "cpu": [ "loong64" ], @@ -2453,9 +2450,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", - "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", + "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", "cpu": [ "mips64el" ], @@ -2469,9 +2466,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", - "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", + "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", "cpu": [ "ppc64" ], @@ -2485,9 +2482,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", - "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", + "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", "cpu": [ "riscv64" ], @@ -2501,9 +2498,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", - "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", + "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", "cpu": [ "s390x" ], @@ -2517,9 +2514,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", - "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", + "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", "cpu": [ "x64" ], @@ -2533,9 +2530,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", - "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", + "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", "cpu": [ "arm64" ], @@ -2549,9 +2546,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", - "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", + "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", "cpu": [ "x64" ], @@ -2565,9 +2562,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", - "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", + "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", "cpu": [ "arm64" ], @@ -2581,9 +2578,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", - "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", + "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", "cpu": [ "x64" ], @@ -2597,9 +2594,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", - "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", + "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", "cpu": [ "x64" ], @@ -2613,9 +2610,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", - "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", + "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", "cpu": [ "arm64" ], @@ -2629,9 +2626,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", - "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", + "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", "cpu": [ "ia32" ], @@ -2645,9 +2642,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", - "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", + "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", "cpu": [ "x64" ], @@ -5089,9 +5086,9 @@ } }, "node_modules/@opentelemetry/api-logs": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.56.0.tgz", - "integrity": "sha512-Wr39+94UNNG3Ei9nv3pHd4AJ63gq5nSemMRpCd8fPwDL9rN3vK26lzxfH27mw16XzOSO+TpyQwBAMaLxaPWG0g==", + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", + "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", "dependencies": { "@opentelemetry/api": "^1.3.0" }, @@ -5100,9 +5097,9 @@ } }, "node_modules/@opentelemetry/context-async-hooks": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.0.tgz", - "integrity": "sha512-roCetrG/cz0r/gugQm/jFo75UxblVvHaNSRoR0kSSRSzXFAiIBqFCZuH458BHBNRtRe+0yJdIJ21L9t94bw7+g==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", + "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", "engines": { "node": ">=14" }, @@ -5111,9 +5108,9 @@ } }, "node_modules/@opentelemetry/core": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.0.tgz", - "integrity": "sha512-Q/3u/K73KUjTCnFUP97ZY+pBjQ1kPEgjOfXj/bJl8zW7GbXdkw6cwuyZk6ZTXkVgCBsYRYUzx4fvYK1jxdb9MA==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", "dependencies": { "@opentelemetry/semantic-conventions": "1.28.0" }, @@ -5125,11 +5122,11 @@ } }, "node_modules/@opentelemetry/instrumentation": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.56.0.tgz", - "integrity": "sha512-2KkGBKE+FPXU1F0zKww+stnlUxUTlBvLCiWdP63Z9sqXYeNI/ziNzsxAp4LAdUcTQmXjw1IWgvm5CAb/BHy99w==", + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", + "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", "dependencies": { - "@opentelemetry/api-logs": "0.56.0", + "@opentelemetry/api-logs": "0.57.2", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", @@ -5144,12 +5141,12 @@ } }, "node_modules/@opentelemetry/instrumentation-amqplib": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.45.0.tgz", - "integrity": "sha512-SlKLsOS65NGMIBG1Lh/hLrMDU9WzTUF25apnV6ZmWZB1bBmUwan7qrwwrTu1cL5LzJWCXOdZPuTaxP7pC9qxnQ==", + "version": "0.46.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.46.1.tgz", + "integrity": "sha512-AyXVnlCf/xV3K/rNumzKxZqsULyITJH6OVLiW6730JPRqWA7Zc9bvYoVNpN6iOpTU8CasH34SU/ksVJmObFibQ==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.1", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5160,12 +5157,12 @@ } }, "node_modules/@opentelemetry/instrumentation-connect": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.42.0.tgz", - "integrity": "sha512-bOoYHBmbnq/jFaLHmXJ55VQ6jrH5fHDMAPjFM0d3JvR0dvIqW7anEoNC33QqYGFYUfVJ50S0d/eoyF61ALqQuA==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.43.0.tgz", + "integrity": "sha512-Q57JGpH6T4dkYHo9tKXONgLtxzsh1ZEW5M9A/OwKrZFyEpLqWgjhcZ3hIuVvDlhb426iDF1f9FPToV/mi5rpeA==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/connect": "3.4.36" }, @@ -5185,11 +5182,11 @@ } }, "node_modules/@opentelemetry/instrumentation-dataloader": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.15.0.tgz", - "integrity": "sha512-5fP35A2jUPk4SerVcduEkpbRAIoqa2PaP5rWumn01T1uSbavXNccAr3Xvx1N6xFtZxXpLJq4FYqGFnMgDWgVng==", + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.16.0.tgz", + "integrity": "sha512-88+qCHZC02up8PwKHk0UQKLLqGGURzS3hFQBZC7PnGwReuoKjHXS1o29H58S+QkXJpkTr2GACbx8j6mUoGjNPA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0" + "@opentelemetry/instrumentation": "^0.57.0" }, "engines": { "node": ">=14" @@ -5199,12 +5196,12 @@ } }, "node_modules/@opentelemetry/instrumentation-express": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.46.0.tgz", - "integrity": "sha512-BCEClDj/HPq/1xYRAlOr6z+OUnbp2eFp18DSrgyQz4IT9pkdYk8eWHnMi9oZSqlC6J5mQzkFmaW5RrKb1GLQhg==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.0.tgz", + "integrity": "sha512-XFWVx6k0XlU8lu6cBlCa29ONtVt6ADEjmxtyAyeF2+rifk8uBJbk1La0yIVfI0DoKURGbaEDTNelaXG9l/lNNQ==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5215,12 +5212,12 @@ } }, "node_modules/@opentelemetry/instrumentation-fastify": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.43.0.tgz", - "integrity": "sha512-Lmdsg7tYiV+K3/NKVAQfnnLNGmakUOFdB0PhoTh2aXuSyCmyNnnDvhn2MsArAPTZ68wnD5Llh5HtmiuTkf+DyQ==", + "version": "0.44.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fastify/-/instrumentation-fastify-0.44.1.tgz", + "integrity": "sha512-RoVeMGKcNttNfXMSl6W4fsYoCAYP1vi6ZAWIGhBY+o7R9Y0afA7f9JJL0j8LHbyb0P0QhSYk+6O56OwI2k4iRQ==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5231,12 +5228,12 @@ } }, "node_modules/@opentelemetry/instrumentation-fs": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.18.0.tgz", - "integrity": "sha512-kC40y6CEMONm8/MWwoF5GHWIC7gOdF+g3sgsjfwJaUkgD6bdWV+FgG0XApqSbTQndICKzw3RonVk8i7s6mHqhA==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.19.0.tgz", + "integrity": "sha512-JGwmHhBkRT2G/BYNV1aGI+bBjJu4fJUD/5/Jat0EWZa2ftrLV3YE8z84Fiij/wK32oMZ88eS8DI4ecLGZhpqsQ==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0" + "@opentelemetry/instrumentation": "^0.57.0" }, "engines": { "node": ">=14" @@ -5246,11 +5243,11 @@ } }, "node_modules/@opentelemetry/instrumentation-generic-pool": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.42.0.tgz", - "integrity": "sha512-J4QxqiQ1imtB9ogzsOnHra0g3dmmLAx4JCeoK3o0rFes1OirljNHnO8Hsj4s1jAir8WmWvnEEQO1y8yk6j2tog==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.43.0.tgz", + "integrity": "sha512-at8GceTtNxD1NfFKGAuwtqM41ot/TpcLh+YsGe4dhf7gvv1HW/ZWdq6nfRtS6UjIvZJOokViqLPJ3GVtZItAnQ==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0" + "@opentelemetry/instrumentation": "^0.57.0" }, "engines": { "node": ">=14" @@ -5260,11 +5257,11 @@ } }, "node_modules/@opentelemetry/instrumentation-graphql": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.46.0.tgz", - "integrity": "sha512-tplk0YWINSECcK89PGM7IVtOYenXyoOuhOQlN0X0YrcDUfMS4tZMKkVc0vyhNWYYrexnUHwNry2YNBNugSpjlQ==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.47.0.tgz", + "integrity": "sha512-Cc8SMf+nLqp0fi8oAnooNEfwZWFnzMiBHCGmDFYqmgjPylyLmi83b+NiTns/rKGwlErpW0AGPt0sMpkbNlzn8w==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0" + "@opentelemetry/instrumentation": "^0.57.0" }, "engines": { "node": ">=14" @@ -5274,12 +5271,12 @@ } }, "node_modules/@opentelemetry/instrumentation-hapi": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.44.0.tgz", - "integrity": "sha512-4HdNIMNXWK1O6nsaQOrACo83QWEVoyNODTdVDbUqtqXiv2peDfD0RAPhSQlSGWLPw3S4d9UoOmrV7s2HYj6T2A==", + "version": "0.45.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.45.1.tgz", + "integrity": "sha512-VH6mU3YqAKTePPfUPwfq4/xr049774qWtfTuJqVHoVspCLiT3bW+fCQ1toZxt6cxRPYASoYaBsMA3CWo8B8rcw==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5290,12 +5287,12 @@ } }, "node_modules/@opentelemetry/instrumentation-http": { - "version": "0.56.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.56.0.tgz", - "integrity": "sha512-/bWHBUAq8VoATnH9iLk5w8CE9+gj+RgYSUphe7hry472n6fYl7+4PvuScoQMdmSUTprKq/gyr2kOWL6zrC7FkQ==", + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.1.tgz", + "integrity": "sha512-ThLmzAQDs7b/tdKI3BV2+yawuF09jF111OFsovqT1Qj3D8vjwKBwhi/rDE5xethwn4tSXtZcJ9hBsVAlWFQZ7g==", "dependencies": { - "@opentelemetry/core": "1.29.0", - "@opentelemetry/instrumentation": "0.56.0", + "@opentelemetry/core": "1.30.1", + "@opentelemetry/instrumentation": "0.57.1", "@opentelemetry/semantic-conventions": "1.28.0", "forwarded-parse": "2.1.2", "semver": "^7.5.2" @@ -5307,26 +5304,42 @@ "@opentelemetry/api": "^1.3.0" } }, - "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.29.0.tgz", - "integrity": "sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA==", + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/api-logs": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.1.tgz", + "integrity": "sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.28.0" + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/instrumentation": { + "version": "0.57.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.1.tgz", + "integrity": "sha512-SgHEKXoVxOjc20ZYusPG3Fh+RLIZTSa4x8QtD3NfgAUDyqdFFS9W1F2ZVbZkqDCdyMcQG02Ok4duUGLHJXHgbA==", + "dependencies": { + "@opentelemetry/api-logs": "0.57.1", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.10.0" + "@opentelemetry/api": "^1.3.0" } }, "node_modules/@opentelemetry/instrumentation-ioredis": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.46.0.tgz", - "integrity": "sha512-sOdsq8oGi29V58p1AkefHvuB3l2ymP1IbxRIX3y4lZesQWKL8fLhBmy8xYjINSQ5gHzWul2yoz7pe7boxhZcqQ==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.47.0.tgz", + "integrity": "sha512-4HqP9IBC8e7pW9p90P3q4ox0XlbLGme65YTrA3UTLvqvo4Z6b0puqZQP203YFu8m9rE/luLfaG7/xrwwqMUpJw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/redis-common": "^0.36.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, @@ -5338,11 +5351,11 @@ } }, "node_modules/@opentelemetry/instrumentation-kafkajs": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.6.0.tgz", - "integrity": "sha512-MGQrzqEUAl0tacKJUFpuNHJesyTi51oUzSVizn7FdvJplkRIdS11FukyZBZJEscofSEdk7Ycmg+kNMLi5QHUFg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.7.0.tgz", + "integrity": "sha512-LB+3xiNzc034zHfCtgs4ITWhq6Xvdo8bsq7amR058jZlf2aXXDrN9SV4si4z2ya9QX4tz6r4eZJwDkXOp14/AQ==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5353,11 +5366,11 @@ } }, "node_modules/@opentelemetry/instrumentation-knex": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.43.0.tgz", - "integrity": "sha512-mOp0TRQNFFSBj5am0WF67fRO7UZMUmsF3/7HSDja9g3H4pnj+4YNvWWyZn4+q0rGrPtywminAXe0rxtgaGYIqg==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.44.0.tgz", + "integrity": "sha512-SlT0+bLA0Lg3VthGje+bSZatlGHw/vwgQywx0R/5u9QC59FddTQSPJeWNw29M6f8ScORMeUOOTwihlQAn4GkJQ==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5368,12 +5381,12 @@ } }, "node_modules/@opentelemetry/instrumentation-koa": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.46.0.tgz", - "integrity": "sha512-RcWXMQdJQANnPUaXbHY5G0Fg6gmleZ/ZtZeSsekWPaZmQq12FGk0L1UwodIgs31OlYfviAZ4yTeytoSUkgo5vQ==", + "version": "0.47.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.0.tgz", + "integrity": "sha512-HFdvqf2+w8sWOuwtEXayGzdZ2vWpCKEQv5F7+2DSA74Te/Cv4rvb2E5So5/lh+ok4/RAIPuvCbCb/SHQFzMmbw==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5384,11 +5397,11 @@ } }, "node_modules/@opentelemetry/instrumentation-lru-memoizer": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.43.0.tgz", - "integrity": "sha512-fZc+1eJUV+tFxaB3zkbupiA8SL3vhDUq89HbDNg1asweYrEb9OlHIB+Ot14ZiHUc1qCmmWmZHbPTwa56mVVwzg==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.44.0.tgz", + "integrity": "sha512-Tn7emHAlvYDFik3vGU0mdwvWJDwtITtkJ+5eT2cUquct6nIs+H8M47sqMJkCpyPe5QIBJoTOHxmc6mj9lz6zDw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0" + "@opentelemetry/instrumentation": "^0.57.0" }, "engines": { "node": ">=14" @@ -5398,11 +5411,11 @@ } }, "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.50.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.50.0.tgz", - "integrity": "sha512-DtwJMjYFXFT5auAvv8aGrBj1h3ciA/dXQom11rxL7B1+Oy3FopSpanvwYxJ+z0qmBrQ1/iMuWELitYqU4LnlkQ==", + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.51.0.tgz", + "integrity": "sha512-cMKASxCX4aFxesoj3WK8uoQ0YUrRvnfxaO72QWI2xLu5ZtgX/QvdGBlU3Ehdond5eb74c2s1cqRQUIptBnKz1g==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5413,12 +5426,12 @@ } }, "node_modules/@opentelemetry/instrumentation-mongoose": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.45.0.tgz", - "integrity": "sha512-zHgNh+A01C5baI2mb5dAGyMC7DWmUpOfwpV8axtC0Hd5Uzqv+oqKgKbVDIVhOaDkPxjgVJwYF9YQZl2pw2qxIA==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.46.0.tgz", + "integrity": "sha512-mtVv6UeaaSaWTeZtLo4cx4P5/ING2obSqfWGItIFSunQBrYROfhuVe7wdIrFUs2RH1tn2YYpAJyMaRe/bnTTIQ==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5429,11 +5442,11 @@ } }, "node_modules/@opentelemetry/instrumentation-mysql": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.44.0.tgz", - "integrity": "sha512-al7jbXvT/uT1KV8gdNDzaWd5/WXf+mrjrsF0/NtbnqLa0UUFGgQnoK3cyborgny7I+KxWhL8h7YPTf6Zq4nKsg==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.45.0.tgz", + "integrity": "sha512-tWWyymgwYcTwZ4t8/rLDfPYbOTF3oYB8SxnYMtIQ1zEf5uDm90Ku3i6U/vhaMyfHNlIHvDhvJh+qx5Nc4Z3Acg==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/mysql": "2.15.26" }, @@ -5445,11 +5458,11 @@ } }, "node_modules/@opentelemetry/instrumentation-mysql2": { - "version": "0.44.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.44.0.tgz", - "integrity": "sha512-e9QY4AGsjGFwmfHd6kBa4yPaQZjAq2FuxMb0BbKlXCAjG+jwqw+sr9xWdJGR60jMsTq52hx3mAlE3dUJ9BipxQ==", + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.45.0.tgz", + "integrity": "sha512-qLslv/EPuLj0IXFvcE3b0EqhWI8LKmrgRPIa4gUd8DllbBpqJAvLNJSv3cC6vWwovpbSI3bagNO/3Q2SuXv2xA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@opentelemetry/sql-common": "^0.40.1" }, @@ -5461,11 +5474,11 @@ } }, "node_modules/@opentelemetry/instrumentation-nestjs-core": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.43.0.tgz", - "integrity": "sha512-NEo4RU7HTjiaXk3curqXUvCb9alRiFWxQY//+hvDXwWLlADX2vB6QEmVCeEZrKO+6I/tBrI4vNdAnbCY9ldZVg==", + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-nestjs-core/-/instrumentation-nestjs-core-0.44.0.tgz", + "integrity": "sha512-t16pQ7A4WYu1yyQJZhRKIfUNvl5PAaF2pEteLvgJb/BWdd1oNuU1rOYt4S825kMy+0q4ngiX281Ss9qiwHfxFQ==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0" }, "engines": { @@ -5476,12 +5489,12 @@ } }, "node_modules/@opentelemetry/instrumentation-pg": { - "version": "0.49.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.49.0.tgz", - "integrity": "sha512-3alvNNjPXVdAPdY1G7nGRVINbDxRK02+KAugDiEpzw0jFQfU8IzFkSWA4jyU4/GbMxKvHD+XIOEfSjpieSodKw==", + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.50.0.tgz", + "integrity": "sha512-TtLxDdYZmBhFswm8UIsrDjh/HFBeDXd4BLmE8h2MxirNHewLJ0VS9UUddKKEverb5Sm2qFVjqRjcU+8Iw4FJ3w==", "dependencies": { "@opentelemetry/core": "^1.26.0", - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "1.27.0", "@opentelemetry/sql-common": "^0.40.1", "@types/pg": "8.6.1", @@ -5503,11 +5516,11 @@ } }, "node_modules/@opentelemetry/instrumentation-redis-4": { - "version": "0.45.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.45.0.tgz", - "integrity": "sha512-Sjgym1xn3mdxPRH5CNZtoz+bFd3E3NlGIu7FoYr4YrQouCc9PbnmoBcmSkEdDy5LYgzNildPgsjx9l0EKNjKTQ==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis-4/-/instrumentation-redis-4-0.46.0.tgz", + "integrity": "sha512-aTUWbzbFMFeRODn3720TZO0tsh/49T8H3h8vVnVKJ+yE36AeW38Uj/8zykQ/9nO8Vrtjr5yKuX3uMiG/W8FKNw==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/redis-common": "^0.36.2", "@opentelemetry/semantic-conventions": "^1.27.0" }, @@ -5519,11 +5532,11 @@ } }, "node_modules/@opentelemetry/instrumentation-tedious": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.17.0.tgz", - "integrity": "sha512-yRBz2409an03uVd1Q2jWMt3SqwZqRFyKoWYYX3hBAtPDazJ4w5L+1VOij71TKwgZxZZNdDBXImTQjii+VeuzLg==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.18.0.tgz", + "integrity": "sha512-9zhjDpUDOtD+coeADnYEJQ0IeLVCj7w/hqzIutdp5NqS1VqTAanaEfsEcSypyvYv5DX3YOsTUoF+nr2wDXPETA==", "dependencies": { - "@opentelemetry/instrumentation": "^0.56.0", + "@opentelemetry/instrumentation": "^0.57.0", "@opentelemetry/semantic-conventions": "^1.27.0", "@types/tedious": "^4.0.14" }, @@ -5535,12 +5548,12 @@ } }, "node_modules/@opentelemetry/instrumentation-undici": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.9.0.tgz", - "integrity": "sha512-lxc3cpUZ28CqbrWcUHxGW/ObDpMOYbuxF/ZOzeFZq54P9uJ2Cpa8gcrC9F716mtuiMaekwk8D6n34vg/JtkkxQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.10.0.tgz", + "integrity": "sha512-vm+V255NGw9gaSsPD6CP0oGo8L55BffBc8KnxqsMuc6XiAD1L8SFNzsW0RHhxJFqy9CJaJh+YiJ5EHXuZ5rZBw==", "dependencies": { "@opentelemetry/core": "^1.8.0", - "@opentelemetry/instrumentation": "^0.56.0" + "@opentelemetry/instrumentation": "^0.57.0" }, "engines": { "node": ">=14" @@ -5558,11 +5571,11 @@ } }, "node_modules/@opentelemetry/resources": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.0.tgz", - "integrity": "sha512-5mGMjL0Uld/99t7/pcd7CuVtJbkARckLVuiOX84nO8RtLtIz0/J6EOHM2TGvPZ6F4K+XjUq13gMx14w80SVCQg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", "dependencies": { - "@opentelemetry/core": "1.30.0", + "@opentelemetry/core": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { @@ -5573,12 +5586,12 @@ } }, "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.0.tgz", - "integrity": "sha512-RKQDaDIkV7PwizmHw+rE/FgfB2a6MBx+AEVVlAHXRG1YYxLiBpPX2KhmoB99R5vA4b72iJrjle68NDWnbrE9Dg==", + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", "dependencies": { - "@opentelemetry/core": "1.30.0", - "@opentelemetry/resources": "1.30.0", + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", "@opentelemetry/semantic-conventions": "1.28.0" }, "engines": { @@ -7430,9 +7443,9 @@ "devOptional": true }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz", - "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.2.tgz", + "integrity": "sha512-JkdNEq+DFxZfUwxvB58tHMHBHVgX23ew41g1OQinthJ+ryhdRk67O31S7sYw8u2lTjHUPFxwar07BBt1KHp/hg==", "cpu": [ "arm" ], @@ -7443,9 +7456,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz", - "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.2.tgz", + "integrity": "sha512-13unNoZ8NzUmnndhPTkWPWbX3vtHodYmy+I9kuLxN+F+l+x3LdVF7UCu8TWVMt1POHLh6oDHhnOA04n8oJZhBw==", "cpu": [ "arm64" ], @@ -7456,9 +7469,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz", - "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.2.tgz", + "integrity": "sha512-Gzf1Hn2Aoe8VZzevHostPX23U7N5+4D36WJNHK88NZHCJr7aVMG4fadqkIf72eqVPGjGc0HJHNuUaUcxiR+N/w==", "cpu": [ "arm64" ], @@ -7469,9 +7482,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz", - "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.2.tgz", + "integrity": "sha512-47N4hxa01a4x6XnJoskMKTS8XZ0CZMd8YTbINbi+w03A2w4j1RTlnGHOz/P0+Bg1LaVL6ufZyNprSg+fW5nYQQ==", "cpu": [ "x64" ], @@ -7482,9 +7495,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz", - "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.2.tgz", + "integrity": "sha512-8t6aL4MD+rXSHHZUR1z19+9OFJ2rl1wGKvckN47XFRVO+QL/dUSpKA2SLRo4vMg7ELA8pzGpC+W9OEd1Z/ZqoQ==", "cpu": [ "arm64" ], @@ -7495,9 +7508,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz", - "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.2.tgz", + "integrity": "sha512-C+AyHBzfpsOEYRFjztcYUFsH4S7UsE9cDtHCtma5BK8+ydOZYgMmWg1d/4KBytQspJCld8ZIujFMAdKG1xyr4Q==", "cpu": [ "x64" ], @@ -7508,9 +7521,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz", - "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.2.tgz", + "integrity": "sha512-de6TFZYIvJwRNjmW3+gaXiZ2DaWL5D5yGmSYzkdzjBDS3W+B9JQ48oZEsmMvemqjtAFzE16DIBLqd6IQQRuG9Q==", "cpu": [ "arm" ], @@ -7521,9 +7534,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz", - "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.2.tgz", + "integrity": "sha512-urjaEZubdIkacKc930hUDOfQPysezKla/O9qV+O89enqsqUmQm8Xj8O/vh0gHg4LYfv7Y7UsE3QjzLQzDYN1qg==", "cpu": [ "arm" ], @@ -7534,9 +7547,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz", - "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.2.tgz", + "integrity": "sha512-KlE8IC0HFOC33taNt1zR8qNlBYHj31qGT1UqWqtvR/+NuCVhfufAq9fxO8BMFC22Wu0rxOwGVWxtCMvZVLmhQg==", "cpu": [ "arm64" ], @@ -7547,9 +7560,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz", - "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.2.tgz", + "integrity": "sha512-j8CgxvfM0kbnhu4XgjnCWJQyyBOeBI1Zq91Z850aUddUmPeQvuAy6OiMdPS46gNFgy8gN1xkYyLgwLYZG3rBOg==", "cpu": [ "arm64" ], @@ -7560,9 +7573,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz", - "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.2.tgz", + "integrity": "sha512-Ybc/1qUampKuRF4tQXc7G7QY9YRyeVSykfK36Y5Qc5dmrIxwFhrOzqaVTNoZygqZ1ZieSWTibfFhQ5qK8jpWxw==", "cpu": [ "loong64" ], @@ -7573,9 +7586,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz", - "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.2.tgz", + "integrity": "sha512-3FCIrnrt03CCsZqSYAOW/k9n625pjpuMzVfeI+ZBUSDT3MVIFDSPfSUgIl9FqUftxcUXInvFah79hE1c9abD+Q==", "cpu": [ "ppc64" ], @@ -7586,9 +7599,22 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz", - "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.2.tgz", + "integrity": "sha512-QNU7BFHEvHMp2ESSY3SozIkBPaPBDTsfVNGx3Xhv+TdvWXFGOSH2NJvhD1zKAT6AyuuErJgbdvaJhYVhVqrWTg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.2.tgz", + "integrity": "sha512-5W6vNYkhgfh7URiXTO1E9a0cy4fSgfE4+Hl5agb/U1sa0kjOLMLC1wObxwKxecE17j0URxuTrYZZME4/VH57Hg==", "cpu": [ "riscv64" ], @@ -7599,9 +7625,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz", - "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.2.tgz", + "integrity": "sha512-B7LKIz+0+p348JoAL4X/YxGx9zOx3sR+o6Hj15Y3aaApNfAshK8+mWZEf759DXfRLeL2vg5LYJBB7DdcleYCoQ==", "cpu": [ "s390x" ], @@ -7612,9 +7638,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz", - "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.2.tgz", + "integrity": "sha512-lG7Xa+BmBNwpjmVUbmyKxdQJ3Q6whHjMjzQplOs5Z+Gj7mxPtWakGHqzMqNER68G67kmCX9qX57aRsW5V0VOng==", "cpu": [ "x64" ], @@ -7625,9 +7651,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz", - "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.2.tgz", + "integrity": "sha512-tD46wKHd+KJvsmije4bUskNuvWKFcTOIM9tZ/RrmIvcXnbi0YK/cKS9FzFtAm7Oxi2EhV5N2OpfFB348vSQRXA==", "cpu": [ "x64" ], @@ -7638,9 +7664,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz", - "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.2.tgz", + "integrity": "sha512-Bjv/HG8RRWLNkXwQQemdsWw4Mg+IJ29LK+bJPW2SCzPKOUaMmPEppQlu/Fqk1d7+DX3V7JbFdbkh/NMmurT6Pg==", "cpu": [ "arm64" ], @@ -7651,9 +7677,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz", - "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.2.tgz", + "integrity": "sha512-dt1llVSGEsGKvzeIO76HToiYPNPYPkmjhMHhP00T9S4rDern8P2ZWvWAQUEJ+R1UdMWJ/42i/QqJ2WV765GZcA==", "cpu": [ "ia32" ], @@ -7664,9 +7690,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz", - "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.2.tgz", + "integrity": "sha512-bwspbWB04XJpeElvsp+DCylKfF4trJDa2Y9Go8O6A7YLX2LIKGcNK/CYImJN6ZP4DcuOHB4Utl3iCbnR62DudA==", "cpu": [ "x64" ], @@ -8173,52 +8199,52 @@ } }, "node_modules/@sentry/core": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.47.0.tgz", - "integrity": "sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.55.0.tgz", + "integrity": "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA==", "engines": { "node": ">=14.18" } }, "node_modules/@sentry/node": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.47.0.tgz", - "integrity": "sha512-tMzeU3KkmDi2OVvSu+Ah5pwoi7srsSyc1DovBbRQU96RFf/lOFzGe9JERa1MyDUqqLH95NqnPTNsa4Amb8/Vxg==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-8.55.0.tgz", + "integrity": "sha512-h10LJLDTRAzYgay60Oy7moMookqqSZSviCWkkmHZyaDn+4WURnPp5SKhhfrzPRQcXKrweiOwDSHBgn1tweDssg==", "dependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/context-async-hooks": "^1.29.0", - "@opentelemetry/core": "^1.29.0", - "@opentelemetry/instrumentation": "^0.56.0", - "@opentelemetry/instrumentation-amqplib": "^0.45.0", - "@opentelemetry/instrumentation-connect": "0.42.0", - "@opentelemetry/instrumentation-dataloader": "0.15.0", - "@opentelemetry/instrumentation-express": "0.46.0", - "@opentelemetry/instrumentation-fastify": "0.43.0", - "@opentelemetry/instrumentation-fs": "0.18.0", - "@opentelemetry/instrumentation-generic-pool": "0.42.0", - "@opentelemetry/instrumentation-graphql": "0.46.0", - "@opentelemetry/instrumentation-hapi": "0.44.0", - "@opentelemetry/instrumentation-http": "0.56.0", - "@opentelemetry/instrumentation-ioredis": "0.46.0", - "@opentelemetry/instrumentation-kafkajs": "0.6.0", - "@opentelemetry/instrumentation-knex": "0.43.0", - "@opentelemetry/instrumentation-koa": "0.46.0", - "@opentelemetry/instrumentation-lru-memoizer": "0.43.0", - "@opentelemetry/instrumentation-mongodb": "0.50.0", - "@opentelemetry/instrumentation-mongoose": "0.45.0", - "@opentelemetry/instrumentation-mysql": "0.44.0", - "@opentelemetry/instrumentation-mysql2": "0.44.0", - "@opentelemetry/instrumentation-nestjs-core": "0.43.0", - "@opentelemetry/instrumentation-pg": "0.49.0", - "@opentelemetry/instrumentation-redis-4": "0.45.0", - "@opentelemetry/instrumentation-tedious": "0.17.0", - "@opentelemetry/instrumentation-undici": "0.9.0", - "@opentelemetry/resources": "^1.29.0", - "@opentelemetry/sdk-trace-base": "^1.29.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/instrumentation-amqplib": "^0.46.0", + "@opentelemetry/instrumentation-connect": "0.43.0", + "@opentelemetry/instrumentation-dataloader": "0.16.0", + "@opentelemetry/instrumentation-express": "0.47.0", + "@opentelemetry/instrumentation-fastify": "0.44.1", + "@opentelemetry/instrumentation-fs": "0.19.0", + "@opentelemetry/instrumentation-generic-pool": "0.43.0", + "@opentelemetry/instrumentation-graphql": "0.47.0", + "@opentelemetry/instrumentation-hapi": "0.45.1", + "@opentelemetry/instrumentation-http": "0.57.1", + "@opentelemetry/instrumentation-ioredis": "0.47.0", + "@opentelemetry/instrumentation-kafkajs": "0.7.0", + "@opentelemetry/instrumentation-knex": "0.44.0", + "@opentelemetry/instrumentation-koa": "0.47.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.44.0", + "@opentelemetry/instrumentation-mongodb": "0.51.0", + "@opentelemetry/instrumentation-mongoose": "0.46.0", + "@opentelemetry/instrumentation-mysql": "0.45.0", + "@opentelemetry/instrumentation-mysql2": "0.45.0", + "@opentelemetry/instrumentation-nestjs-core": "0.44.0", + "@opentelemetry/instrumentation-pg": "0.50.0", + "@opentelemetry/instrumentation-redis-4": "0.46.0", + "@opentelemetry/instrumentation-tedious": "0.18.0", + "@opentelemetry/instrumentation-undici": "0.10.0", + "@opentelemetry/resources": "^1.30.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0", "@prisma/instrumentation": "5.22.0", - "@sentry/core": "8.47.0", - "@sentry/opentelemetry": "8.47.0", + "@sentry/core": "8.55.0", + "@sentry/opentelemetry": "8.55.0", "import-in-the-middle": "^1.11.2" }, "engines": { @@ -8226,20 +8252,21 @@ } }, "node_modules/@sentry/opentelemetry": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.47.0.tgz", - "integrity": "sha512-wunyBIUPeY6Kx3SFhOQqOPs+hyRADO5bztpo8aZ3N3xfzhefSTOdrgUroKvHx1DvoQO6MAlykcuUFps3yfaqmg==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-8.55.0.tgz", + "integrity": "sha512-UvatdmSr3Xf+4PLBzJNLZ2JjG1yAPWGe/VrJlJAqyTJ2gKeTzgXJJw8rp4pbvNZO8NaTGEYhhO+scLUj0UtLAQ==", "dependencies": { - "@sentry/core": "8.47.0" + "@sentry/core": "8.55.0" }, "engines": { "node": ">=14.18" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", - "@opentelemetry/core": "^1.29.0", - "@opentelemetry/instrumentation": "^0.56.0", - "@opentelemetry/sdk-trace-base": "^1.29.0", + "@opentelemetry/context-async-hooks": "^1.30.1", + "@opentelemetry/core": "^1.30.1", + "@opentelemetry/instrumentation": "^0.57.1", + "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0" } }, @@ -8758,9 +8785,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", "dev": true }, "node_modules/@types/express": { @@ -8808,12 +8835,6 @@ "@types/node": "*" } }, - "node_modules/@types/grecaptcha": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/grecaptcha/-/grecaptcha-3.0.9.tgz", - "integrity": "sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==", - "dev": true - }, "node_modules/@types/http-errors": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", @@ -8914,11 +8935,12 @@ } }, "node_modules/@types/node": { - "version": "20.11.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.7.tgz", - "integrity": "sha512-GPmeN1C3XAyV5uybAf4cMLWT9fDWcmQhZVtMFu7OR32WjrqGG+Wnk2V1d0bmtUyE/Zy1QJ9BxyiTih9z8Oks8A==", + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz", + "integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==", + "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~7.8.0" } }, "node_modules/@types/parse-json": { @@ -9686,6 +9708,11 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/altcha-lib": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/altcha-lib/-/altcha-lib-1.2.0.tgz", + "integrity": "sha512-S5WF8QLNRaM1hvK24XPhOLfu9is2EBCvH7+nv50sM5CaIdUCqQCd0WV/qm/ZZFGTdSoKLuDp+IapZxBLvC+SNg==" + }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -11654,9 +11681,9 @@ } }, "node_modules/esbuild": { - "version": "0.24.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", - "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", + "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "dev": true, "hasInstallScript": true, "bin": { @@ -11666,31 +11693,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.24.2", - "@esbuild/android-arm": "0.24.2", - "@esbuild/android-arm64": "0.24.2", - "@esbuild/android-x64": "0.24.2", - "@esbuild/darwin-arm64": "0.24.2", - "@esbuild/darwin-x64": "0.24.2", - "@esbuild/freebsd-arm64": "0.24.2", - "@esbuild/freebsd-x64": "0.24.2", - "@esbuild/linux-arm": "0.24.2", - "@esbuild/linux-arm64": "0.24.2", - "@esbuild/linux-ia32": "0.24.2", - "@esbuild/linux-loong64": "0.24.2", - "@esbuild/linux-mips64el": "0.24.2", - "@esbuild/linux-ppc64": "0.24.2", - "@esbuild/linux-riscv64": "0.24.2", - "@esbuild/linux-s390x": "0.24.2", - "@esbuild/linux-x64": "0.24.2", - "@esbuild/netbsd-arm64": "0.24.2", - "@esbuild/netbsd-x64": "0.24.2", - "@esbuild/openbsd-arm64": "0.24.2", - "@esbuild/openbsd-x64": "0.24.2", - "@esbuild/sunos-x64": "0.24.2", - "@esbuild/win32-arm64": "0.24.2", - "@esbuild/win32-ia32": "0.24.2", - "@esbuild/win32-x64": "0.24.2" + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" } }, "node_modules/escalade": { @@ -13066,16 +13093,18 @@ } }, "node_modules/formidable": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.2.tgz", - "integrity": "sha512-Jqc1btCy3QzRbJaICGwKcBfGWuLADRerLzDqi2NwSt/UkXLsHJw2TVResiaoBufHVHy9aSgClOHCeJsSsFLTbg==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, - "license": "MIT", "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", - "hexoid": "^2.0.0", "once": "^1.4.0" }, + "engines": { + "node": ">=14.0.0" + }, "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" } @@ -13493,16 +13522,6 @@ "node": ">= 0.4" } }, - "node_modules/hexoid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-2.0.0.tgz", - "integrity": "sha512-qlspKUK7IlSQv2o+5I7yhUd7TxlOG2Vr5LTa3ve2XSNVKAL/n/u/7KLvKmFNimomDIKvZFXWHv0T12mv7rT8Aw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -16224,9 +16243,9 @@ } }, "node_modules/pg-protocol": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.7.0.tgz", - "integrity": "sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==" + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.9.5.tgz", + "integrity": "sha512-DYTWtWpfd5FOro3UnAfwvhD8jh59r2ig8bPtc9H8Ds7MscE/9NYruUQWFAOuraRl29jwcT2kyMFQ3MxeaVjUhg==" }, "node_modules/pg-types": { "version": "2.2.0", @@ -16363,9 +16382,9 @@ } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -16381,7 +16400,7 @@ } ], "dependencies": { - "nanoid": "^3.3.7", + "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -16821,14 +16840,12 @@ } }, "node_modules/react-router": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz", - "integrity": "sha512-39sXJkftkKWRZ2oJtHhCxmoCrBCULr/HAH4IT5DHlgu/Q0FCPV0S4Lx+abjDTx/74xoZzNYDYbOZWlJjruyuDQ==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.6.0.tgz", + "integrity": "sha512-GGufuHIVCJDbnIAXP3P9Sxzq3UUsddG3rrI3ut1q6m0FI6vxVBF3JoPQ38+W/blslLH4a5Yutp8drkEpXoddGQ==", "dependencies": { - "@types/cookie": "^0.6.0", "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0", - "turbo-stream": "2.4.0" + "set-cookie-parser": "^2.6.0" }, "engines": { "node": ">=20.0.0" @@ -16844,11 +16861,11 @@ } }, "node_modules/react-router-dom": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.1.tgz", - "integrity": "sha512-vSrQHWlJ5DCfyrhgo0k6zViOe9ToK8uT5XGSmnuC2R3/g261IdIMpZVqfjD6vWSXdnf5Czs4VA/V60oVR6/jnA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.6.0.tgz", + "integrity": "sha512-DYgm6RDEuKdopSyGOWZGtDfSm7Aofb8CCzgkliTjtu/eDuB0gcsv6qdFhhi8HdtmA+KHkt5MfZ5K2PdzjugYsA==", "dependencies": { - "react-router": "7.1.1" + "react-router": "7.6.0" }, "engines": { "node": ">=20.0.0" @@ -16858,11 +16875,6 @@ "react-dom": ">=18" } }, - "node_modules/react-router/node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" - }, "node_modules/react-router/node_modules/cookie": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", @@ -17037,11 +17049,6 @@ "node": ">=4" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/regenerator-transform": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", @@ -17257,12 +17264,12 @@ } }, "node_modules/rollup": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz", - "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==", + "version": "4.40.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.2.tgz", + "integrity": "sha512-tfUOg6DTP4rhQ3VjOO6B4wyrJnGOX85requAXvqYTHsOgb2TFJdZ3aWpT8W2kPoypSGP7dZUyzxJ9ee4buM5Fg==", "dev": true, "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.7" }, "bin": { "rollup": "dist/bin/rollup" @@ -17272,25 +17279,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.29.1", - "@rollup/rollup-android-arm64": "4.29.1", - "@rollup/rollup-darwin-arm64": "4.29.1", - "@rollup/rollup-darwin-x64": "4.29.1", - "@rollup/rollup-freebsd-arm64": "4.29.1", - "@rollup/rollup-freebsd-x64": "4.29.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.29.1", - "@rollup/rollup-linux-arm-musleabihf": "4.29.1", - "@rollup/rollup-linux-arm64-gnu": "4.29.1", - "@rollup/rollup-linux-arm64-musl": "4.29.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.29.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1", - "@rollup/rollup-linux-riscv64-gnu": "4.29.1", - "@rollup/rollup-linux-s390x-gnu": "4.29.1", - "@rollup/rollup-linux-x64-gnu": "4.29.1", - "@rollup/rollup-linux-x64-musl": "4.29.1", - "@rollup/rollup-win32-arm64-msvc": "4.29.1", - "@rollup/rollup-win32-ia32-msvc": "4.29.1", - "@rollup/rollup-win32-x64-msvc": "4.29.1", + "@rollup/rollup-android-arm-eabi": "4.40.2", + "@rollup/rollup-android-arm64": "4.40.2", + "@rollup/rollup-darwin-arm64": "4.40.2", + "@rollup/rollup-darwin-x64": "4.40.2", + "@rollup/rollup-freebsd-arm64": "4.40.2", + "@rollup/rollup-freebsd-x64": "4.40.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.2", + "@rollup/rollup-linux-arm-musleabihf": "4.40.2", + "@rollup/rollup-linux-arm64-gnu": "4.40.2", + "@rollup/rollup-linux-arm64-musl": "4.40.2", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-gnu": "4.40.2", + "@rollup/rollup-linux-riscv64-musl": "4.40.2", + "@rollup/rollup-linux-s390x-gnu": "4.40.2", + "@rollup/rollup-linux-x64-gnu": "4.40.2", + "@rollup/rollup-linux-x64-musl": "4.40.2", + "@rollup/rollup-win32-arm64-msvc": "4.40.2", + "@rollup/rollup-win32-ia32-msvc": "4.40.2", + "@rollup/rollup-win32-x64-msvc": "4.40.2", "fsevents": "~2.3.2" } }, @@ -18559,6 +18567,48 @@ "node": ">=0.8" } }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -18793,12 +18843,12 @@ "dev": true }, "node_modules/tsx": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", - "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", + "version": "4.19.4", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", + "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", "dev": true, "dependencies": { - "esbuild": "~0.23.0", + "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "bin": { @@ -18811,434 +18861,6 @@ "fsevents": "~2.3.3" } }, - "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/tsx/node_modules/esbuild": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", - "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.1", - "@esbuild/android-arm": "0.23.1", - "@esbuild/android-arm64": "0.23.1", - "@esbuild/android-x64": "0.23.1", - "@esbuild/darwin-arm64": "0.23.1", - "@esbuild/darwin-x64": "0.23.1", - "@esbuild/freebsd-arm64": "0.23.1", - "@esbuild/freebsd-x64": "0.23.1", - "@esbuild/linux-arm": "0.23.1", - "@esbuild/linux-arm64": "0.23.1", - "@esbuild/linux-ia32": "0.23.1", - "@esbuild/linux-loong64": "0.23.1", - "@esbuild/linux-mips64el": "0.23.1", - "@esbuild/linux-ppc64": "0.23.1", - "@esbuild/linux-riscv64": "0.23.1", - "@esbuild/linux-s390x": "0.23.1", - "@esbuild/linux-x64": "0.23.1", - "@esbuild/netbsd-x64": "0.23.1", - "@esbuild/openbsd-arm64": "0.23.1", - "@esbuild/openbsd-x64": "0.23.1", - "@esbuild/sunos-x64": "0.23.1", - "@esbuild/win32-arm64": "0.23.1", - "@esbuild/win32-ia32": "0.23.1", - "@esbuild/win32-x64": "0.23.1" - } - }, - "node_modules/turbo-stream": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", - "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -19414,9 +19036,10 @@ "dev": true }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", @@ -19639,14 +19262,17 @@ } }, "node_modules/vite": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.7.tgz", - "integrity": "sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ==", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "dependencies": { - "esbuild": "^0.24.2", - "postcss": "^8.4.49", - "rollup": "^4.23.0" + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -19730,6 +19356,32 @@ "vite": "^2.3.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -20226,6 +19878,7 @@ "@nextui-org/react": "^2.6.11", "@sc07-canvas/lib": "^1.0.0", "@theme-toggles/react": "^4.1.0", + "altcha-lib": "^1.2.0", "eventemitter3": "^5.0.1", "framer-motion": "^11.3.2", "lodash.throttle": "^4.1.1", @@ -20236,7 +19889,6 @@ "vite-plugin-banner": "^0.8.1" }, "devDependencies": { - "@types/grecaptcha": "^3.0.9", "@types/lodash.throttle": "^4.1.9", "@types/socket.io-client": "^3.0.0", "eslint-plugin-react": "^7.33.2", @@ -20288,6 +19940,9 @@ "version": "1.0.0", "dependencies": { "eventemitter3": "^5.0.1" + }, + "devDependencies": { + "altcha-lib": "^1.2.0" } }, "packages/server": { @@ -20299,6 +19954,7 @@ "@sc07-canvas/lib": "^1.0.0", "@sentry/node": "^8.47.0", "@socket.io/redis-adapter": "^8.3.0", + "altcha-lib": "^1.2.0", "body-parser": "^1.20.2", "bullmq": "^5.40.2", "connect-redis": "^8.0.1", @@ -20321,6 +19977,7 @@ "@types/express": "^5.0.0", "@types/express-session": "^1.18.1", "@types/jest": "^29.5.14", + "@types/node": "^24.0.3", "@types/redis-mock": "^0.17.3", "@types/supertest": "^6.0.2", "@types/uuid": "^10.0.0", diff --git a/packages/client/package.json b/packages/client/package.json index 5f8440603f05292c2fca11f8470282a0a20b631a..401d0966e05fac0ce624f2268afef33068086cf2 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -17,6 +17,7 @@ "@nextui-org/react": "^2.6.11", "@sc07-canvas/lib": "^1.0.0", "@theme-toggles/react": "^4.1.0", + "altcha-lib": "^1.2.0", "eventemitter3": "^5.0.1", "framer-motion": "^11.3.2", "lodash.throttle": "^4.1.1", @@ -27,7 +28,6 @@ "vite-plugin-banner": "^0.8.1" }, "devDependencies": { - "@types/grecaptcha": "^3.0.9", "@types/lodash.throttle": "^4.1.9", "@types/socket.io-client": "^3.0.0", "eslint-plugin-react": "^7.33.2", diff --git a/packages/client/src/Moderator/Moderator.tsx b/packages/client/src/Moderator/Moderator.tsx index 31f5275dd601f013c4debd042c2317f7f7c8255c..c0495d78072370e9c5ce5c5ffc219533dd31d318 100644 --- a/packages/client/src/Moderator/Moderator.tsx +++ b/packages/client/src/Moderator/Moderator.tsx @@ -3,6 +3,9 @@ import { UserModSidebar } from "./UserModSidebar"; import { KeybindManager } from "../lib/keybinds"; import { ModSidebar } from "./ModSidebar"; import { useHasRole } from "../hooks/useHasRole"; +import { ModeratorModule } from "./ModeratorModule"; + +ModeratorModule.get(); // initialize const context = createContext<{ state: IModeratorContext; @@ -103,6 +106,12 @@ export const ModeratorContext = ({ children }: React.PropsWithChildren) => { ); useEffect(() => { + if (isMod) { + ModeratorModule.get().connect(); + } else { + ModeratorModule.get().socket.disconnect(); + } + const handleKeybind = () => { if (!isMod) { console.warn("TOGGLE_MOD_MENU canceled, user is not a moderator"); diff --git a/packages/client/src/Moderator/ModeratorModule.ts b/packages/client/src/Moderator/ModeratorModule.ts new file mode 100644 index 0000000000000000000000000000000000000000..b99032bf6a25e939d40a8097479507c58f776827 --- /dev/null +++ b/packages/client/src/Moderator/ModeratorModule.ts @@ -0,0 +1,47 @@ +import { Debug } from "@sc07-canvas/lib/src/debug"; +import { + ModClientToServerEvents, + ModServerToClientEvents, +} from "@sc07-canvas/lib/src/net"; +import { io, Socket } from "socket.io-client"; + +export class ModeratorModule { + private static instance: ModeratorModule; + socket: Socket = io( + "/mod", + { autoConnect: false } + ); + + private constructor() { + Debug.controllers.set("Moderator", this); + + this.socket.on("connect", () => { + console.log("connected to mod socket"); + }); + + this.socket.on("connect_error", (err) => { + if (this.socket.active) { + console.log("disconnected temporarily"); + } else { + console.log("failed to connect", err); + } + }); + + this.socket.on("disconnect", () => { + console.log("disconnected"); + }); + + this.socket.on("captcha", (...data) => { + console.log(...data); + }); + } + + static get() { + if (!this.instance) this.instance = new ModeratorModule(); + return this.instance; + } + + connect() { + this.socket.connect(); + } +} diff --git a/packages/client/src/Moderator/UserModSidebar.tsx b/packages/client/src/Moderator/UserModSidebar.tsx index 6d2035cded3b22b8261c2c5ce0c7e8518f5efa94..f272eb7b2cbb4c87f94809e08b7ebc78ef2f99a9 100644 --- a/packages/client/src/Moderator/UserModSidebar.tsx +++ b/packages/client/src/Moderator/UserModSidebar.tsx @@ -16,6 +16,7 @@ import { import { CalendarDateTime, parseDateTime } from "@internationalized/date"; import { toast } from "react-toastify"; import { EError } from "@sc07-canvas/lib"; +import { ModeratorModule } from "./ModeratorModule"; export const UserModSidebar = () => { const { state, dispatch } = useModerator(); @@ -81,11 +82,164 @@ const Inner = ({ sub }: { sub: string }) => { + + + ); }; +type CaptchaStatus = "WAITING" | "INVALID" | "PASSED"; +const CaptchaStatusColors: { + [k in CaptchaStatus]: + | "default" + | "success" + | "warning" + | "primary" + | "secondary" + | "danger"; +} = { + WAITING: "default", + INVALID: "danger", + PASSED: "success", +}; + +const Captcha = ({ sub }: { sub: string }) => { + const [status, setStatus] = useState<{ + [k: string]: CaptchaStatus; + }>({}); + const [socketStatus, setSocketStatus] = useState<{ + [k: string]: "NEW" | "GONE"; + }>({}); + + const sockets = useQuery("/mod/user/{sub}/sockets", { + params: { + path: { + sub, + }, + }, + }); + + const sendCaptcha = useCallback( + (socketId?: string) => { + oapi.POST( + socketId + ? "/mod/user/{sub}/captcha/{socket}" + : "/mod/user/{sub}/captcha", + { + params: { + path: { + sub, + socket: socketId, + }, + }, + } + ); + }, + [sub] + ); + + useEffect(() => { + console.log("captcha & sockets loaded"); + + setStatus({}); + const handleStatus = ( + id: number, + userId: string, + socketId: string, + status: CaptchaStatus + ) => { + setStatus((v) => ({ + ...v, + [socketId]: status, + })); + }; + + const handleConnect = (id: string) => { + setSocketStatus((v) => ({ + ...v, + [id]: "NEW", + })); + }; + + const handleDisconnect = (id: string) => { + setSocketStatus((v) => ({ + ...v, + [id]: "GONE", + })); + }; + + const mod = ModeratorModule.get(); + + mod.socket.emit("join", "captcha"); + mod.socket.emit("join", "user:" + sub); + mod.socket.on("captcha", handleStatus); + mod.socket.on("socketConnect", handleConnect); + mod.socket.on("socketDisconnect", handleDisconnect); + + return () => { + console.log("captcha & sockets unloaded"); + mod.socket.emit("leave", "captcha"); + mod.socket.emit("leave", "user:" + sub); + mod.socket.off("captcha", handleStatus); + mod.socket.off("socketConnect", handleConnect); + mod.socket.off("socketDisconnect", handleDisconnect); + }; + }, [sub]); + + return ( + <> + + + {sockets.data?.sockets.map((socket) => ( + + {socket.id} + + + } + > + + + )) || null} + + + ); +}; + +const SocketChip = ({ status }: { status?: "NEW" | "GONE" }) => { + switch (status) { + case "NEW": + return ( + + New + + ); + case "GONE": + return ( + + Gone + + ); + default: + <>; + } +}; + +const CaptchaChip = ({ status }: { status?: CaptchaStatus }) => { + if (!status) return <>; + return ( + + {status} + + ); +}; + const Notice = ({ sub }: { sub: string }) => { const [loading, setLoading] = useState(false); const [title, setTitle] = useState(""); diff --git a/packages/client/src/components/Captcha/CaptchaStatusBar.tsx b/packages/client/src/components/Captcha/CaptchaStatusBar.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b620f4a34f2382f65c80ec1504d8f3f42aaf261a --- /dev/null +++ b/packages/client/src/components/Captcha/CaptchaStatusBar.tsx @@ -0,0 +1,78 @@ +import { motion } from "framer-motion"; +import { Card, CardBody } from "@nextui-org/react"; +import { useEffect, useRef, useState } from "react"; +import { CaptchaService, CaptchaServiceStatus } from "../../lib/captcha"; + +const Timer = () => { + const ref = useRef(null); + + useEffect(() => { + let _timer = 0; + + const timer = setInterval(() => { + _timer++; + let text = (_timer + "").split(""); + text.splice(-1, 0, "."); + if (ref.current) ref.current.innerText = text.join("") + "s"; + }, 100); + + return () => { + clearInterval(timer); + }; + }, []); + + return ; +}; + +export const CaptchaStatusBar = () => { + const [status, setStatus] = useState("IDLE"); + + useEffect(() => { + const service = CaptchaService.get(); + + setStatus(service.status); + + function handleStatus(status: CaptchaServiceStatus) { + setStatus(status); + } + service.on("status", handleStatus); + + return () => { + service.off("status", handleStatus); + }; + }, []); + + useEffect(() => { + if (status === "IDLE") { + } + }, [status]); + + return ( +
+ + + +

Captcha running...

+

+ Using{" "} + + Altcha + {" "} + • {status === "WORK" && } +

+
+
+
+
+ ); +}; diff --git a/packages/client/src/components/Info/InfoPrivacy.tsx b/packages/client/src/components/Info/InfoPrivacy.tsx index e5e59da2269ecb04479746bfbc9b56b06cd92f5f..84f7c7c90f8a99b1e11c827c38542d528abd788a 100644 --- a/packages/client/src/components/Info/InfoPrivacy.tsx +++ b/packages/client/src/components/Info/InfoPrivacy.tsx @@ -1,5 +1,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faShieldHalved } from "@fortawesome/free-solid-svg-icons"; +import { Link } from "@nextui-org/react"; export const InfoPrivacy = () => { return ( @@ -11,8 +12,13 @@ export const InfoPrivacy = () => {
  • - Google Invisible Recaptcha is used to help prevent bots. Google's - privacy policy and terms are available below. + + altcha-lib + {" "} + is used for proof-of-work captcha verification
  • Usernames should not be assumed to be private
diff --git a/packages/client/src/components/Info/InfoSidebar.tsx b/packages/client/src/components/Info/InfoSidebar.tsx index 35c2120a1106c1d9c07d6f51b13b6419901b668f..1989b29af0812445f5b857f8fea30fc346c25e24 100644 --- a/packages/client/src/components/Info/InfoSidebar.tsx +++ b/packages/client/src/components/Info/InfoSidebar.tsx @@ -30,7 +30,6 @@ export const InfoSidebar = () => {

Build {__COMMIT_HASH__}

-

© 2023 - {__BUILD_YEAR__}{" "} {

+ {showMobileTools && } diff --git a/packages/client/src/index.tsx b/packages/client/src/index.tsx index 69523b8adb91a297a408b5da2332aae431208138..2fe8e0d107dd0ed3dbd0317997e0325e122e94c2 100644 --- a/packages/client/src/index.tsx +++ b/packages/client/src/index.tsx @@ -5,6 +5,7 @@ import { NextUIProvider } from "@nextui-org/react"; import { ThemeProvider } from "next-themes"; import App from "./components/App"; +import "./lib/captcha"; import * as Sentry from "@sentry/react"; import { printBanner } from "./lib/banner"; diff --git a/packages/client/src/lib/captcha.ts b/packages/client/src/lib/captcha.ts new file mode 100644 index 0000000000000000000000000000000000000000..7f47954aadb27fbefc58d192d250d1b4e80d1293 --- /dev/null +++ b/packages/client/src/lib/captcha.ts @@ -0,0 +1,64 @@ +import { solveChallenge } from "altcha-lib"; +import { Challenge, Payload, Solution } from "altcha-lib/types"; +import EventEmitter from "eventemitter3"; + +export type CaptchaServiceStatus = "WORK" | "IDLE"; + +interface Events { + status: (status: CaptchaServiceStatus) => void; +} + +export class CaptchaService extends EventEmitter { + private static instance: CaptchaService; + private _status: CaptchaServiceStatus = "IDLE"; + + static get() { + if (this.instance) return this.instance; + + return (this.instance = new CaptchaService()); + } + + get status() { + return this._status; + } + + private setStatus(status: CaptchaServiceStatus) { + this._status = status; + this.emit("status", status); + } + + private createPayload(data: Challenge, solution: Solution) { + return btoa( + JSON.stringify({ + algorithm: data.algorithm, + challenge: data.challenge, + salt: data.salt, + signature: data.signature, + number: solution.number, + took: solution.took, + } satisfies Payload & { took: number }) + ); + } + + solve(challenge: Challenge) { + this.setStatus("WORK"); + console.log("[CaptchaService] Start captcha solve..."); + console.time("[CaptchaService] solve"); + const response = solveChallenge( + challenge.challenge, + challenge.salt, + challenge.algorithm, + challenge.maxnumber + ); + + return { + promise: response.promise.then(async (data) => { + this.setStatus("IDLE"); + console.timeEnd("[CaptchaService] solve"); + if (!data) return data; + + return this.createPayload(challenge, data); + }), + }; + } +} diff --git a/packages/client/src/lib/network.ts b/packages/client/src/lib/network.ts index edff395ad0081e403b7bc0c18bda904ae36f7436..c4f0f470c3c262df8b226c3fcdece769b58e1eba 100644 --- a/packages/client/src/lib/network.ts +++ b/packages/client/src/lib/network.ts @@ -11,7 +11,8 @@ import { } from "@sc07-canvas/lib/src/net"; import { toast } from "react-toastify"; import { handleAlert, handleDismiss } from "./alerts"; -import { Recaptcha } from "./recaptcha"; +import { CaptchaService } from "./captcha"; +import { Debug } from "@sc07-canvas/lib/src/debug"; export interface INetworkEvents { connected: () => void; @@ -65,6 +66,8 @@ class Network extends EventEmitter { constructor() { super(); + Debug._network = this; + this.socket.on("connect", () => { console.log("Connected to server"); toast.success("Connected to server"); @@ -99,12 +102,12 @@ class Network extends EventEmitter { console.log("Reconnect failed"); }); - this.socket.on("recaptcha", (site_key) => { - Recaptcha.load(site_key); - }); - - this.socket.on("recaptcha_challenge", (ack) => { - Recaptcha.executeChallenge(ack); + this.socket.on("captcha_challenge", (challenge, ack) => { + CaptchaService.get() + .solve(challenge) + .promise.then((token) => { + ack(token); + }); }); this.socket.on("user", (user) => { diff --git a/packages/client/src/lib/recaptcha.ts b/packages/client/src/lib/recaptcha.ts deleted file mode 100644 index 0746f3357d7ee6f91f9be9ee65686c99d858cfd4..0000000000000000000000000000000000000000 --- a/packages/client/src/lib/recaptcha.ts +++ /dev/null @@ -1,32 +0,0 @@ -class Recaptcha_ { - load(site_key: string) { - const script = document.createElement("script"); - script.setAttribute( - "src", - `https://www.google.com/recaptcha/api.js?render=explicit` - ); - document.head.appendChild(script); - - script.onload = () => { - grecaptcha.ready(() => { - grecaptcha.render("grecaptcha-badge", { - sitekey: site_key, - badge: "inline", - size: "invisible", - }); - - console.log("Google Recaptcha Loaded!"); - }); - }; - } - - executeChallenge(ack: (token: string) => void) { - console.log("[Recaptcha] Received challenge request..."); - grecaptcha.execute().then((token) => { - console.log("[Recaptcha] Sending challenge token back"); - ack(token as any); - }); - } -} - -export const Recaptcha = new Recaptcha_(); diff --git a/packages/lib/package.json b/packages/lib/package.json index 8c2ea80df10b91475f822c089d9cde55758a0d4b..6b9893cae4ebe02dda9346a01b1911a7207a905e 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -8,5 +8,8 @@ }, "dependencies": { "eventemitter3": "^5.0.1" + }, + "devDependencies": { + "altcha-lib": "^1.2.0" } } diff --git a/packages/lib/src/debug.ts b/packages/lib/src/debug.ts index 7702449a67ed16868923fa0013873a505b479598..1f8967ee15b1af441280103890acde7a5c02c1da 100644 --- a/packages/lib/src/debug.ts +++ b/packages/lib/src/debug.ts @@ -101,6 +101,11 @@ class FlagManager extends EventEmitter { class Debugcl extends EventEmitter { readonly flags = new FlagManager(); _getRenderer: any; + _network: any; + /** + * name -> instance + */ + readonly controllers: Map = new Map(); constructor() { super(); @@ -185,6 +190,10 @@ class Debugcl extends EventEmitter { getRenderer() { return this._getRenderer(); } + + getNetwork() { + return this._network; + } } const Debug = new Debugcl(); diff --git a/packages/lib/src/net.ts b/packages/lib/src/net.ts index cee0c807076dc221a0040aff05dd0abd226dc5f4..e0ee55c8ef25d091113c304e55f1b6d98ea03e69 100644 --- a/packages/lib/src/net.ts +++ b/packages/lib/src/net.ts @@ -1,3 +1,5 @@ +import type { Challenge } from "altcha-lib/types"; + // socket.io export type Subscription = "heatmap"; @@ -28,8 +30,10 @@ export interface ServerToClientEvents { alert: (alert: IAlert) => void; alert_dismiss: (id: string) => void; - recaptcha: (site_key: string) => void; - recaptcha_challenge: (ack: (token: string) => void) => void; + captcha_challenge: ( + challenge: Challenge, + ack: (token: string | null) => void + ) => void; /* --- subscribe events --- */ @@ -70,6 +74,33 @@ export interface ClientToServerEvents { subscribe: (topic: Subscription) => void; unsubscribe: (topic: Subscription) => void; + + debug: (key: string, ...rest: any[]) => void; +} + +export interface ModServerToClientEvents { + /** + * @room captcha + */ + captcha: ( + id: number, + userId: string, + socketId: string, + result: "WAITING" | "INVALID" | "PASSED" + ) => void; + + /** + * @room user:{sub} + */ + socketConnect: (socketId: string) => void; + socketDisconnect: (socketId: string) => void; + pixelPlace: (socketId: string, x: number, y: number) => void; + pixelUndo: (socketId: string, x: number, y: number) => void; +} + +export interface ModClientToServerEvents { + join: (room: string) => void; + leave: (room: string) => void; } export interface IPosition { diff --git a/packages/server/package.json b/packages/server/package.json index b06fe18157ee6ccdd10d1f995628cf8237077cd1..de2ab8222c8b97eccbda998137592fbae4d59280 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -27,6 +27,7 @@ "@types/express": "^5.0.0", "@types/express-session": "^1.18.1", "@types/jest": "^29.5.14", + "@types/node": "^24.0.3", "@types/redis-mock": "^0.17.3", "@types/supertest": "^6.0.2", "@types/uuid": "^10.0.0", @@ -47,6 +48,7 @@ "@sc07-canvas/lib": "^1.0.0", "@sentry/node": "^8.47.0", "@socket.io/redis-adapter": "^8.3.0", + "altcha-lib": "^1.2.0", "body-parser": "^1.20.2", "bullmq": "^5.40.2", "connect-redis": "^8.0.1", diff --git a/packages/server/prisma/migrations/20250621000533_add_captcha_challenge/migration.sql b/packages/server/prisma/migrations/20250621000533_add_captcha_challenge/migration.sql new file mode 100644 index 0000000000000000000000000000000000000000..17d41063d370245b3746c86944f330881f00c28e --- /dev/null +++ b/packages/server/prisma/migrations/20250621000533_add_captcha_challenge/migration.sql @@ -0,0 +1,20 @@ +-- CreateEnum +CREATE TYPE "CaptchaState" AS ENUM ('WAITING', 'INVALID', 'PASSED'); + +-- CreateTable +CREATE TABLE "CaptchaChallenge" ( + "id" SERIAL NOT NULL, + "userSub" TEXT, + "socketId" TEXT NOT NULL, + "challenge" TEXT NOT NULL, + "responseToken" TEXT, + "serverMetrics" JSONB NOT NULL, + "state" "CaptchaState" NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "CaptchaChallenge_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "CaptchaChallenge" ADD CONSTRAINT "CaptchaChallenge_userSub_fkey" FOREIGN KEY ("userSub") REFERENCES "User"("sub") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/packages/server/prisma/schema.prisma b/packages/server/prisma/schema.prisma index fe172f1a486e6904cb9182dbe96bbf4a1a1c2c25..16f95e30c57df5bfa77e9910b8d904fcb888c97e 100644 --- a/packages/server/prisma/schema.prisma +++ b/packages/server/prisma/schema.prisma @@ -29,12 +29,34 @@ model User { isAdmin Boolean @default(false) isModerator Boolean @default(false) - pixels Pixel[] - FactionMember FactionMember[] - Ban Ban? - AuditLog AuditLog[] - IPAddress IPAddress[] - PixelReport PixelReport[] + pixels Pixel[] + FactionMember FactionMember[] + Ban Ban? + AuditLog AuditLog[] + IPAddress IPAddress[] + PixelReport PixelReport[] + CaptchaChallenge CaptchaChallenge[] +} + +enum CaptchaState { + WAITING + INVALID + PASSED +} + +model CaptchaChallenge { + id Int @id @default(autoincrement()) + userSub String? + socketId String + challenge String // stringified json + responseToken String? + serverMetrics Json + state CaptchaState + + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt + + user User? @relation(fields: [userSub], references: [sub], onDelete: SetNull) } model Instance { diff --git a/packages/server/src/__test__/api/client.test.ts b/packages/server/src/__test__/api/client.test.ts index 1cb2cf790b0ece9607512e8835989244ddf279bb..40df6b4f721e148d30043eedb20ca01b4e784470 100644 --- a/packages/server/src/__test__/api/client.test.ts +++ b/packages/server/src/__test__/api/client.test.ts @@ -472,7 +472,7 @@ describe.skip("Client endpoints /api", () => { const CanvasController = ( await import("../../controllers/CanvasController") ).CanvasController; - const Settings = (await import("../../lib/Settings")).Settings; + const Settings = (await import("../../settings/Settings")).Settings; mockReset(prismaMock); prismaMock.setting.findMany.mockResolvedValue([ @@ -485,7 +485,7 @@ describe.skip("Client endpoints /api", () => { value: JSON.stringify({ width: 100, height: 100 }), }, ]); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await CanvasController.initialize(); ExpressController.initialize(); @@ -570,7 +570,7 @@ describe.skip("Client endpoints /api", () => { .ExpressController; CanvasController = (await import("../../controllers/CanvasController")) .CanvasController; - const Settings = (await import("../../lib/Settings")).Settings; + const Settings = (await import("../../settings/Settings")).Settings; mockReset(prismaMock); prismaMock.setting.findMany.mockResolvedValue([ @@ -583,7 +583,7 @@ describe.skip("Client endpoints /api", () => { value: JSON.stringify({ width: 100, height: 100 }), }, ]); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await CanvasController.initialize(); ExpressController.initialize(); diff --git a/packages/server/src/__test__/controllers/canvas.test.ts b/packages/server/src/__test__/controllers/canvas.test.ts index 2923a26ded976eb10ff7cac02e90a1ae200d936e..1a6fcb7feff03bb66d0e57a3126ad817f757fa4a 100644 --- a/packages/server/src/__test__/controllers/canvas.test.ts +++ b/packages/server/src/__test__/controllers/canvas.test.ts @@ -8,6 +8,9 @@ jest.mock("../../controllers/SocketController", () => { broadcastConfig: jest.fn(), handleConnection: jest.fn(), setupMasterShard: jest.fn(), + getUserFromSocket: jest.fn(), + getUserSockets: jest.fn(), + MOD_NS: jest.fn(), }; return { @@ -37,12 +40,12 @@ import { mockReset } from "jest-mock-extended"; import { type CanvasController as ICanvasController } from "../../controllers/CanvasController"; import { type Redis as IRedis } from "../../controllers/RedisController"; import { type SocketController as ISocketController } from "../../controllers/SocketController"; -import { type Settings as ISettings } from "../../lib/Settings"; +import { type Settings as ISettings } from "../../settings/Settings"; import { type Palette as IPalette } from "../../utils/Palette"; import type * as IWorkers from "../../workers/worker"; import { prismaMock } from "../_prisma.mock"; -// jest.mock("../../lib/Settings", () => { +// jest.mock("../../settings/Settings", () => { // return { // Settings // } @@ -97,11 +100,11 @@ describe("Canvas", () => { .CanvasController; SocketController = (await import("../../controllers/SocketController")) .SocketController; - Settings = (await import("../../lib/Settings")).Settings; + Settings = (await import("../../settings/Settings")).Settings; Palette = (await import("../../utils/Palette")).Palette; setupPrismaMock(prismaMock); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await Palette.load(); // Redis.initialize(); @@ -141,11 +144,11 @@ describe("Canvas", () => { .CanvasController; SocketController = (await import("../../controllers/SocketController")) .SocketController; - Settings = (await import("../../lib/Settings")).Settings; + Settings = (await import("../../settings/Settings")).Settings; Palette = (await import("../../utils/Palette")).Palette; setupPrismaMock(prismaMock); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await Palette.load(); // Redis.initialize(); @@ -213,11 +216,11 @@ describe("Canvas", () => { .CanvasController; SocketController = (await import("../../controllers/SocketController")) .SocketController; - Settings = (await import("../../lib/Settings")).Settings; + Settings = (await import("../../settings/Settings")).Settings; Palette = (await import("../../utils/Palette")).Palette; setupPrismaMock(prismaMock); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await Palette.load(); // Redis.initialize(); @@ -323,11 +326,11 @@ describe("Canvas", () => { .CanvasController; // SocketController = (await import("../../controllers/SocketController")) // .SocketController; - Settings = (await import("../../lib/Settings")).Settings; + Settings = (await import("../../settings/Settings")).Settings; Palette = (await import("../../utils/Palette")).Palette; setupPrismaMock(prismaMock); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await Palette.load(); // Redis.initialize(); @@ -991,11 +994,11 @@ describe("Canvas", () => { .CanvasController; // SocketController = (await import("../../controllers/SocketController")) // .SocketController; - Settings = (await import("../../lib/Settings")).Settings; + Settings = (await import("../../settings/Settings")).Settings; Palette = (await import("../../utils/Palette")).Palette; setupPrismaMock(prismaMock); - await Settings.loadAllSettings(); + await Settings.get().initialize(); await Palette.load(); // Redis.initialize(); diff --git a/packages/server/src/__test__/lib/express.test.ts b/packages/server/src/__test__/lib/express.test.ts index 9eacc216602e917dc4b3d58e0fbe2f608d113db7..ac7f82163bdb5fddeaf231bfb486f5b041263700 100644 --- a/packages/server/src/__test__/lib/express.test.ts +++ b/packages/server/src/__test__/lib/express.test.ts @@ -4,7 +4,7 @@ import request from "supertest"; import { type ExpressController as IExpressController } from "../../controllers/ExpressController"; import { type prismaMock as IPrismaMock } from "../_prisma.mock"; -jest.mock("../../lib/Settings"); +jest.mock("../../settings/Settings"); jest.mock("connect-redis"); jest.mock("express", () => { const real = jest.requireActual("express"); diff --git a/packages/server/src/api/mod/users.ts b/packages/server/src/api/mod/users.ts index 7cfca3adcf8b0f6d2ae73ebf90fc4d90a637a977..c4e96bc036353e72eafe237790eaf7893fc513ab 100644 --- a/packages/server/src/api/mod/users.ts +++ b/packages/server/src/api/mod/users.ts @@ -1,5 +1,6 @@ import { Prisma } from "@prisma/client"; +import { CaptchaController } from "../../controllers/CaptchaController"; import { SocketController } from "../../controllers/SocketController"; import { getLogger } from "../../lib/Logger"; import { prisma } from "../../lib/prisma"; @@ -101,6 +102,75 @@ export class UsersEndpoints extends Router { res.json({ success: true }); } + @Router.handler("get", "/:sub/sockets") + async getSockets(req: Router.Request, res: Router.Response) { + let user: User; + + try { + user = await User.fromSub(req.params.sub); + } catch (e) { + if (e instanceof UserNotFound) { + res.status(404).json({ success: false, error: "User not found" }); + } else { + Logger.error( + `/user/${req.params.sub}/sockets Error ` + (e as any)?.message + ); + res.status(500).json({ success: false, error: "Internal error" }); + } + return; + } + + const sockets = await SocketController.get().getUserSockets(user.sub); + + res.json({ + sockets: sockets.map((s) => ({ id: s.id })), + }); + } + + @Router.handler("post", "/:sub/captcha/:socket?") + async sendCaptcha(req: Router.Request, res: Router.Response) { + let user: User; + + try { + user = await User.fromSub(req.params.sub); + } catch (e) { + if (e instanceof UserNotFound) { + res.status(404).json({ success: false, error: "User not found" }); + } else { + Logger.error( + `/user/${req.params.sub}/captcha Error ` + (e as any)?.message + ); + res.status(500).json({ success: false, error: "Internal error" }); + } + return; + } + + const Captcha = CaptchaController.get(); + + if (typeof req.params.socket === "string") { + const sockets = await SocketController.get() + .io.in(req.params.socket) + .fetchSockets(); + res.json({ + challenges: await Promise.allSettled( + sockets.map((socket) => Captcha.challenge(socket)) + ), + }); + return; + } + + const sockets = await SocketController.get().getUserSockets(user.sub); + if (!sockets.length) { + return res.status(400).json({ error: "User is not connected" }); + } + + const challenges = await Promise.allSettled( + sockets.map((socket) => Captcha.challenge(socket)) + ); + + res.json({ challenges }); + } + /** * Get all of a user's IP addresses * diff --git a/packages/server/src/api/openapi.yml b/packages/server/src/api/openapi.yml index 95dd77645d91456cca68fe65aa96c8744a0d8cb8..2bdd138f61c08b9417875a98c17cc59d4f8587b6 100644 --- a/packages/server/src/api/openapi.yml +++ b/packages/server/src/api/openapi.yml @@ -165,6 +165,58 @@ paths: description: Query all users /mod/user/@all/notice: description: Send notice to all users + /mod/user/{sub}/sockets: + parameters: + - $ref: "#/components/parameters/UserSub" + get: + summary: Get all sockets owned by a user + responses: + 200: + description: Successful + content: + application/json: + schema: + type: object + required: + - sockets + properties: + sockets: + type: array + items: + type: object + required: + - id + properties: + id: + type: string + /mod/user/{sub}/captcha: + parameters: + - $ref: "#/components/parameters/UserSub" + post: + summary: Send captcha to user + responses: + 200: + description: Success + content: + application/json: + schema: + type: object + /mod/user/{sub}/captcha/{socket}: + parameters: + - $ref: "#/components/parameters/UserSub" + - in: path + name: socket + schema: + type: string + post: + summary: Send captcha to user + responses: + 200: + description: Success + content: + application/json: + schema: + type: object /mod/user/{sub}/ips: description: Get all of user's IP addresses parameters: diff --git a/packages/server/src/controllers/CanvasController.ts b/packages/server/src/controllers/CanvasController.ts index 6df2e265103ed34739c1f44513d215f229a0be3d..b8b7030c952775c94f1b8dcf12748f657705c2a2 100644 --- a/packages/server/src/controllers/CanvasController.ts +++ b/packages/server/src/controllers/CanvasController.ts @@ -8,8 +8,8 @@ import { Socket } from "socket.io"; import { getLogger } from "../lib/Logger"; import { prisma } from "../lib/prisma"; -import { Settings } from "../lib/Settings"; import { ClientConfigService } from "../services/ClientConfigService"; +import { Settings } from "../settings/Settings"; import { callCacheWorker, getCacheWorkerIdForCoords } from "../workers/worker"; import { Redis } from "./RedisController"; import { SocketController } from "./SocketController"; @@ -44,10 +44,10 @@ export class CanvasController { const instance = (CanvasController.instance = new CanvasController()); // set values - const canvasSize = Settings.quickGet("canvas.size", true, false); + const canvasSize = Settings.get("canvas.size"); instance.canvasSize = [canvasSize.width, canvasSize.height]; - const canvasFrozen = Settings.quickGet("canvas.frozen", true, false); + const canvasFrozen = Settings.get("canvas.frozen"); instance.isFrozen = canvasFrozen; // run sideeffects diff --git a/packages/server/src/controllers/CaptchaController.ts b/packages/server/src/controllers/CaptchaController.ts new file mode 100644 index 0000000000000000000000000000000000000000..b3da1a0cf844ffcd2a5c9566d369e7a68235edc6 --- /dev/null +++ b/packages/server/src/controllers/CaptchaController.ts @@ -0,0 +1,200 @@ +import { $Enums } from "@prisma/client"; +import { createChallenge, extractParams, verifySolution } from "altcha-lib"; +import { Payload } from "altcha-lib/types"; +import EventEmitter from "events"; + +import { prisma } from "../lib/prisma"; +import { Secrets } from "../lib/Secrets"; +import { Settings } from "../settings/Settings"; +import { tryParseJSON } from "../utils/tryParseJSON"; +import { RemoteSocket, Socket, SocketController } from "./SocketController"; + +interface Events { + solve: [ + id: number, + userId: string, + socketId: string, + state: $Enums.CaptchaState, + ]; +} + +// TODO: implement random checks (see #maybeChallenge) + +export class CaptchaController extends EventEmitter { + private static instance: CaptchaController | undefined; + private static readonly Secrets = new Secrets(["CAPTCHA_HMAC_SECRET"]); + + private constructor() { + super(); + + this.on("solve", (...data) => { + SocketController.get() + .MOD_NS.to("captcha") + .emit("captcha", ...data); + }); + } + + static validateEnvironment() { + this.Secrets.load(); + } + + static initialize() { + if (typeof CaptchaController.instance !== "undefined") { + throw new Error("CaptchaController#initialize when initialized"); + } + + // initialize class + const instance = (CaptchaController.instance = new CaptchaController()); + + SocketController.addDebug("test_captcha", (socket) => { + instance.challenge(socket); + }); + + return instance; + } + + static get(): CaptchaController { + if (typeof CaptchaController.instance === "undefined") { + throw new Error("CaptchaController#get when not initialized"); + } + + return CaptchaController.instance!; + } + + private get Secrets() { + return CaptchaController.Secrets; + } + + create({ + params, + expires, + }: { + params?: Record; + expires?: Date; + } = {}) { + return createChallenge({ + hmacKey: this.Secrets.get("CAPTCHA_HMAC_SECRET"), + algorithm: Settings.get("captcha.algorithm"), + maxNumber: Settings.get("captcha.maxnumber"), + params, + expires, + }); + } + + verify(payload: string | Payload) { + return verifySolution( + payload, + this.Secrets.get("CAPTCHA_HMAC_SECRET"), + true + ); + } + + async challenge( + socket: Socket | RemoteSocket, + ...args: Parameters + ) { + const challenge = await this.create(...args); + + const user = await SocketController.get().getUserFromSocket(socket); + const captchaChallenge = await prisma.captchaChallenge.create({ + data: { + userSub: user?.sub, + socketId: socket.id, + challenge: JSON.stringify(challenge), + state: "WAITING", + serverMetrics: {}, + }, + }); + this.emit("solve", captchaChallenge.id, user!.sub, socket.id, "WAITING"); + + socket.emit("captcha_challenge", challenge, async (token) => { + const start = Date.now(); + + if (!token) { + // token is null + await prisma.captchaChallenge.update({ + where: { + id: captchaChallenge.id, + }, + data: { + state: "INVALID", + serverMetrics: { + verifyTimeMs: Date.now() - start, + }, + }, + }); + this.emit( + "solve", + captchaChallenge.id, + user!.sub, + socket.id, + "INVALID" + ); + return; + } + + const valid = await this.verify(token); + if (!valid) { + // token is invalid + await prisma.captchaChallenge.update({ + where: { + id: captchaChallenge.id, + }, + data: { + state: "INVALID", + serverMetrics: { + verifyTimeMs: Date.now() - start, + }, + }, + }); + this.emit( + "solve", + captchaChallenge.id, + user!.sub, + socket.id, + "INVALID" + ); + return; + } + + await prisma.captchaChallenge.update({ + where: { + id: captchaChallenge.id, + }, + data: { + state: "PASSED", + responseToken: token, + serverMetrics: { + verifyTimeMs: Date.now() - start, + }, + }, + }); + this.emit("solve", captchaChallenge.id, user!.sub, socket.id, "PASSED"); + }); + + return captchaChallenge; + } + + extractData>( + token: string + ): { server: Record; client: T | null } { + const serverParams = extractParams(token); + const clientParams = tryParseJSON( + Buffer.from(token, "base64").toString() + ); + + return { + server: serverParams, + client: clientParams, + }; + } + + /** + * Roll a dice to send a captcha to a socket + * + * @stub + */ + maybeChallenge(_socket: Socket) { + // TODO: use Settings captcha.enable to determine if random challenges should be issued + } +} diff --git a/packages/server/src/controllers/SocketController.ts b/packages/server/src/controllers/SocketController.ts index 59b1a4cee6205e61c27d7bf9c95c5355cdc3016a..dc2846e4260ea08f868f22d68ac3f00a870a2e30 100644 --- a/packages/server/src/controllers/SocketController.ts +++ b/packages/server/src/controllers/SocketController.ts @@ -2,29 +2,48 @@ import http from "node:http"; import { ClientToServerEvents, + ModClientToServerEvents, + ModServerToClientEvents, Pixel, ServerToClientEvents, } from "@sc07-canvas/lib/src/net"; import { createAdapter } from "@socket.io/redis-adapter"; import { Redis as IORedis } from "ioredis"; -import { Server, Socket as RawSocket } from "socket.io"; +import { + Namespace, + RemoteSocket as RawRemoteSocket, + Server, + Socket as RawSocket, +} from "socket.io"; import { getLogger } from "../lib/Logger"; import { prisma } from "../lib/prisma"; -import { Recaptcha } from "../lib/Recaptcha"; import { User } from "../models/User"; import { ClientConfigService } from "../services/ClientConfigService"; import { CanvasController } from "./CanvasController"; +import { CaptchaController } from "./CaptchaController"; import { ExpressController, ISessionProvider } from "./ExpressController"; import { LockExists, Redis } from "./RedisController"; const Logger = getLogger("SOCKET"); -type Socket = RawSocket; +export type Socket = RawSocket; +export type RemoteSocket = RawRemoteSocket; + +interface Hooks { + socketConnection: (socket: Socket) => void; +} + +type HooksMap = { [k in keyof Hooks]: Hooks[k][] }; export class SocketController { private static instance: SocketController | undefined; + private static hooks: HooksMap = { + socketConnection: [], + }; + private static debugHooks: { [k: string]: (...rest: any[]) => void } = {}; io: Server; + MOD_NS: Namespace; private constructor(server?: http.Server, session?: ISessionProvider) { const pubClient = new IORedis(process.env.REDIS_HOST); @@ -39,8 +58,29 @@ export class SocketController { this.io.engine.use(session); this.io.on("connection", this.handleConnection.bind(this)); + + this.MOD_NS = this.io.of("/mod"); + this.MOD_NS.use(async (socket, next) => { + const user = await this.getUserFromSocket(socket, true); + if (!user || !user.isModerator) { + next(new Error("Not Permitted")); + return; + } + + next(); + }); + this.MOD_NS.on("connection", (socket) => { + socket.on("join", (room) => { + socket.join(room); + }); + + socket.on("leave", (room) => { + socket.leave(room); + }); + }); } else { this.io = new Server({ adapter: createAdapter(pubClient, subClient) }); + this.MOD_NS = this.io.of("/mod"); } } @@ -68,6 +108,27 @@ export class SocketController { } } + static addDebug(key: string, func: (socket: Socket, ...rest: any[]) => void) { + if (process.env.NODE_ENV !== "development") return; + + Logger.debug(`Added debug hook for ${key}`); + this.debugHooks[key] = func; + } + + static hook(hook: Hook, func: Hooks[Hook]) { + this.hooks[hook].push(func); + } + + private static execHook( + hook: Hook, + ...args: Parameters + ) { + for (const func of this.hooks[hook]) { + // @ts-expect-error TS2556 is thrown when not applicable + func(...args); + } + } + static get(): SocketController { if (typeof SocketController.instance === "undefined") { throw new Error("SocketController#get called when not initialized"); @@ -85,10 +146,27 @@ export class SocketController { this.io.emit("config", ClientConfigService.getConfig()); } + async getUserFromSocket(socket: Socket, raw: true): Promise; + async getUserFromSocket( + socket: Socket | RemoteSocket, + raw?: false + ): Promise; + async getUserFromSocket(socket: Socket | RemoteSocket, raw?: boolean) { + if (raw && "request" in socket) { + return ( + socket.request.session.user && + (await User.fromAuthSession(socket.request.session.user)) + ); + } + + const redis = await Redis.getClient(); + const uid = await redis.get(Redis.key("socketToSub", socket.id)); + if (!uid) return undefined; + return await User.fromSub(uid); + } + async handleConnection(socket: Socket) { - const user = - socket.request.session.user && - (await User.fromAuthSession(socket.request.session.user)); + const user = await this.getUserFromSocket(socket, true); Logger.debug( `Socket ${socket.id} connection ` + (user ? "@" + user.sub : "No Auth") ); @@ -117,6 +195,7 @@ export class SocketController { } if (user) { + this.MOD_NS.to(`user:${user.sub}`).emit("socketConnect", socket.id); socket.emit("availablePixels", user.pixelStack); socket.emit("pixelLastPlaced", user.lastTimeGainStarted.getTime()); @@ -133,9 +212,6 @@ export class SocketController { ); } - if (process.env.RECAPTCHA_SITE_KEY) - socket.emit("recaptcha", process.env.RECAPTCHA_SITE_KEY); - socket.emit("config", ClientConfigService.getConfig()); { CanvasController.get() @@ -154,6 +230,10 @@ export class SocketController { socket.on("disconnect", () => { Logger.debug(`Socket ${socket.id} disconnected`); + if (user) { + this.MOD_NS.to(`user:${user.sub}`).emit("socketDisconnect", socket.id); + } + Redis.getClient().then((redis) => { if (user) redis.del(Redis.key("socketToSub", socket.id)); }); @@ -229,7 +309,7 @@ export class SocketController { return; } - Recaptcha.maybeChallenge(socket); + CaptchaController.get().maybeChallenge(socket); await user.modifyStack(-1); await CanvasController.get().setPixel( @@ -254,6 +334,12 @@ export class SocketController { data: newPixel, }); socket.broadcast.emit("pixel", newPixel); + this.MOD_NS.to(`user:${user.sub}`).emit( + "pixelPlace", + socket.id, + newPixel.x, + newPixel.y + ); }); } catch (e) { if (e instanceof LockExists) { @@ -323,6 +409,12 @@ export class SocketController { await CanvasController.get().refreshPixel(pixel.x, pixel.y); ack({ success: true, data: {} }); + this.MOD_NS.to(`user:${user.sub}`).emit( + "pixelUndo", + socket.id, + pixel.x, + pixel.y + ); }); socket.on("subscribe", (topic) => { @@ -332,6 +424,14 @@ export class SocketController { socket.on("unsubscribe", (topic) => { socket.leave("sub:" + topic); }); + + if (process.env.NODE_ENV === "development") { + socket.on("debug", (key, ...rest) => { + SocketController.debugHooks[key]?.(socket, ...rest); + }); + } + + SocketController.execHook("socketConnection", socket); } /** @@ -351,4 +451,9 @@ export class SocketController { this.io.to("sub:heatmap").emit("heatmap", message); }); } + + async getUserSockets(userSub: string): Promise { + const sockets = await this.io.in(`user:${userSub}`).fetchSockets(); + return sockets; + } } diff --git a/packages/server/src/index.main.ts b/packages/server/src/index.main.ts index 332aa37382a8d1ef45df1d3fd5fa52fd876530f7..5f1dbf83b73acccace6f710389cafa8456a67b1f 100644 --- a/packages/server/src/index.main.ts +++ b/packages/server/src/index.main.ts @@ -1,11 +1,12 @@ import { CanvasController } from "./controllers/CanvasController"; +import { CaptchaController } from "./controllers/CaptchaController"; import { ExpressController } from "./controllers/ExpressController"; import { OpenIDController } from "./controllers/OpenIDController"; import { Redis } from "./controllers/RedisController"; import { SocketController } from "./controllers/SocketController"; import { getLogger } from "./lib/Logger"; -import { Settings } from "./lib/Settings"; import { ClientConfigService } from "./services/ClientConfigService"; +import { Settings } from "./settings/Settings"; import { Palette } from "./utils/Palette"; import { spawnCacheWorkers } from "./workers/worker"; @@ -20,12 +21,15 @@ export default () => { }), spawnCacheWorkers(), Palette.load().then(() => - Settings.loadAllSettings().then(async () => { - await ClientConfigService.initialize(); - await CanvasController.initialize(); - ExpressController.initialize(); - SocketController.initialize(); - }) + Settings.get() + .initialize() + .then(async () => { + await ClientConfigService.initialize(); + await CanvasController.initialize(); + ExpressController.initialize(); + SocketController.initialize(); + CaptchaController.initialize(); + }) ), ]).then(() => { Logger.info("Startup tasks have completed, starting server"); diff --git a/packages/server/src/index.worker.ts b/packages/server/src/index.worker.ts index 3f1be73f862c5190e8aea615c8c498372f3339e2..6d24d57ffb0b490de0a176b792f273f907945665 100644 --- a/packages/server/src/index.worker.ts +++ b/packages/server/src/index.worker.ts @@ -1,8 +1,8 @@ import { SocketController } from "./controllers/SocketController"; import { BullMQ_JobManager } from "./jobs/bullmq"; import { getLogger } from "./lib/Logger"; -import { Settings } from "./lib/Settings"; import { ClientConfigService } from "./services/ClientConfigService"; +import { Settings } from "./settings/Settings"; import { Palette } from "./utils/Palette"; const Logger = getLogger("MAIN"); @@ -10,9 +10,11 @@ const Logger = getLogger("MAIN"); export default () => { Promise.all([ Palette.load(), - Settings.loadAllSettings().then(() => { - SocketController.initialize(true); - }), + Settings.get() + .initialize() + .then(() => { + SocketController.initialize(true); + }), ClientConfigService.initialize(), ]).then(() => { Logger.info("Startup tasks completed, starting workers..."); diff --git a/packages/server/src/lib/Logger.ts b/packages/server/src/lib/Logger.ts index 344ba88c5ff65dcd95bfa563e82aab25c12d931d..6a398482b49cdcacd6e876287447b5438d4d4736 100644 --- a/packages/server/src/lib/Logger.ts +++ b/packages/server/src/lib/Logger.ts @@ -69,6 +69,7 @@ export const LoggerType = createEnum([ "CANVAS_WORK", "WORKER_ROOT", "RECAPTCHA", + "SECRETS", ]); export const getLogger = ( diff --git a/packages/server/src/lib/Recaptcha.ts b/packages/server/src/lib/Recaptcha.ts deleted file mode 100644 index 1b29302ae6dea1b7dd4691e93ff6f3598008324c..0000000000000000000000000000000000000000 --- a/packages/server/src/lib/Recaptcha.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { - ClientToServerEvents, - ServerToClientEvents, -} from "@sc07-canvas/lib/src/net"; -import { Socket } from "socket.io"; - -import { User } from "../models/User"; -import { getLogger } from "./Logger"; - -const Logger = getLogger("RECAPTCHA"); - -class Recaptcha_ { - disabled = false; - chance: number | null = null; - - constructor() { - this.disabled = - !process.env.RECAPTCHA_SITE_KEY || - !process.env.RECAPTCHA_SECRET_KEY || - !process.env.RECAPTCHA_PIXEL_CHANCE; - - if (!process.env.RECAPTCHA_PIXEL_CHANCE) { - Logger.warn("No RECAPTCHA_PIXEL_CHANCE set, captchas will not be sent!"); - } else { - this.chance = parseFloat(process.env.RECAPTCHA_PIXEL_CHANCE); - - if (this.chance > 1 || this.chance < 0) { - this.chance = null; - this.disabled = true; - Logger.warn("RECAPTCHA_PIXEL_CHANCE is not within (0 - ): boolean { - if (this.disabled || !this.chance) return false; - - if (Math.random() > this.chance) { - socket.emitWithAck("recaptcha_challenge").then((token) => { - this.verifyToken(token).then(async (data) => { - if (!data.success) { - this.notifyStaffOfError(data).then(() => {}); - } else { - // if (data.score < 0.5 || true) { - // try { - // const user = (await User.fromAuthSession( - // socket.request.session.user! - // ))!; - // this.notifyStaff(user, data.score).then(() => {}); - // } catch (e) {} - // } - } - }); - }); - return true; - } - - return false; - } - - async verifyToken( - token: string - ): Promise< - | { success: true; challenge_ts: string; hostname: string; score: number } - | { success: false; "error-codes": string[] } - > { - return await fetch( - `https://www.google.com/recaptcha/api/siteverify?secret=${process.env.RECAPTCHA_SECRET_KEY!}&response=${token}`, - { - method: "POST", - } - ).then((a) => a.json()); - } - - async notifyStaff(user: User, score: number) { - if (!process.env.DISCORD_WEBHOOK) return; - - return await fetch(process.env.DISCORD_WEBHOOK, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - content: `User ${user.sub} got a low score ${score}`, - }), - }); - } - - async notifyStaffOfError(obj: any) { - if (!process.env.DISCORD_WEBHOOK) return; - - return await fetch(process.env.DISCORD_WEBHOOK, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - content: - "Error while verifying captcha\n```\n" + - JSON.stringify(obj, null, 2) + - "\n```", - }), - }); - } -} - -export const Recaptcha = new Recaptcha_(); diff --git a/packages/server/src/lib/Secrets.ts b/packages/server/src/lib/Secrets.ts new file mode 100644 index 0000000000000000000000000000000000000000..f600358415b46ab98341341ff4fd5d606e164e70 --- /dev/null +++ b/packages/server/src/lib/Secrets.ts @@ -0,0 +1,53 @@ +import fs from "node:fs"; + +import { getLogger } from "./Logger"; + +const Logger = getLogger("SECRETS"); + +export class Secrets { + private secrets: Record; + + constructor(secrets: T[]) { + const builder: any = {}; + for (const secret of secrets) { + builder[secret] = ""; + } + this.secrets = builder; + } + + load() { + for (const secret of Object.keys(this.secrets)) { + this._load(secret as any); + } + } + + private _load(secret: T) { + const RAW = process.env[secret]; + const FILE = process.env[`${secret}_FILE`]; + + if (RAW || FILE) { + let content: string; + if (FILE) { + content = fs.readFileSync(FILE, "utf8"); + } else { + content = RAW as any; + } + + if (!content) + throw new Error( + `${secret} failed to load from ${FILE ? "file" : "environment"}` + ); + + Logger.info(`Loaded ${secret} from ${FILE ? "file" : "environment"}`); + this.secrets[secret] = content; + } else { + throw new Error( + `${secret} or ${secret}_FILE is missing from environment variables` + ); + } + } + + get(secret: T) { + return this.secrets[secret]; + } +} diff --git a/packages/server/src/lib/Settings.ts b/packages/server/src/lib/Settings.ts deleted file mode 100644 index dd9be5143bc7967cba3c4636a115da35357c6a7a..0000000000000000000000000000000000000000 --- a/packages/server/src/lib/Settings.ts +++ /dev/null @@ -1,146 +0,0 @@ -import { getLogger } from "./Logger"; -import { prisma } from "./prisma"; - -const Logger = getLogger("SETTINGS"); - -interface ISettings { - "canvas.frozen"(): boolean; - "canvas.size"(): { width: number; height: number }; -} - -type ISettingValue = ReturnType; -type ISettingKey = keyof ISettings; - -export class SettingNotSetError extends Error { - constructor(settingId: string) { - super("SettingNotSetError: Setting `" + settingId + "` is not set"); - } -} - -export class SettingStaleError extends Error { - constructor(settingId: string) { - super("SettingStaleError: Setting `" + settingId + "` is stale"); - } -} - -type ICachedSetting = { - key: Key; - value?: ISettingValue; - lastFetched: Date; -}; - -const isSettingStale = (cachedSetting: ICachedSetting): boolean => { - // TODO: use a better time - if (Date.now() - cachedSetting.lastFetched.getTime() > 60 * 1000) { - return true; - } - - return false; -}; - -export const Settings = new (class Settings { - #local: ICachedSetting[] = []; - - private upsertLocal( - key: T, - value: ISettingValue | undefined - ) { - const val = this.#local.find((s) => s.key === key); - if (val) { - val.value = JSON.stringify(value); - val.lastFetched = new Date(); - } else { - this.#local.push({ - key, - value: JSON.stringify(value), - lastFetched: new Date(), - }); - } - } - - /** - * Clears all #local & loads fresh settings - */ - async loadAllSettings() { - const settings = await prisma.setting.findMany(); - - this.#local = []; - - for (const setting of settings) { - this.upsertLocal(setting.key as any, JSON.parse(setting.value)); - } - - Logger.debug(`Settings#loadAllSettings loaded ${settings.length} settings`); - } - - get( - settingId: SettingID, - throwUnset: false - ): Promise | undefined>; - get( - settingId: SettingID, - throwUnset: true - ): Promise>; - async get(settingId: string, throwUnset: boolean): Promise { - const setting = await prisma.setting.findFirst({ - where: { key: settingId }, - }); - - this.upsertLocal( - settingId as any, - setting ? JSON.parse(setting.value) : undefined - ); - - if (throwUnset && !setting) throw new SettingNotSetError(settingId); - if (!setting) return undefined; - return JSON.parse(setting.value); - } - - quickGet( - settingId: SettingID, - throwUnset: false, - throwStale: boolean - ): ISettingValue | undefined; - quickGet( - settingId: SettingID, - throwUnset: true, - throwStale: boolean - ): ISettingValue; - quickGet( - settingId: string, - throwUnset: boolean, - throwStale: boolean = false - ): unknown { - const setting = this.#local.find((s) => s.key === settingId); - - if (!setting) { - if (throwUnset) throw new SettingNotSetError(settingId); - return undefined; - } - - if (isSettingStale(setting) && throwStale) { - throw new SettingStaleError(settingId); - } - - return JSON.parse(setting.value); - } - - set( - settingId: SettingID, - value: ISettingValue - ) { - this.upsertLocal(settingId, value); - return prisma.setting.upsert({ - where: { - key: settingId, - }, - create: { - key: settingId, - value: JSON.stringify(value), - }, - update: { - value: JSON.stringify(value), - }, - }); - } -})(); diff --git a/packages/server/src/settings/Settings.ts b/packages/server/src/settings/Settings.ts new file mode 100644 index 0000000000000000000000000000000000000000..476bee4cf74c281012ec28bb5ecc758a1a332d0e --- /dev/null +++ b/packages/server/src/settings/Settings.ts @@ -0,0 +1,85 @@ +import { getLogger } from "../lib/Logger"; +import { CanvasFrozenSetting } from "./canvas/frozen"; +import { CanvasSizeSetting } from "./canvas/size"; +import { CaptchaAlgorithmSetting } from "./captcha/algorithm"; +import { CaptchaEnableSetting } from "./captcha/enable"; +import { CaptchaMaxNumberSetting } from "./captcha/maxnumber"; +import { ISettingKey, ISettingValue, Setting } from "./setting.class"; + +const Logger = getLogger("SETTINGS"); + +type AllSettings = Record>; + +export class Settings { + private static instance: Settings; + settings: AllSettings = {} as any; + + private constructor() { + this.register("canvas.frozen", new CanvasFrozenSetting()); + this.register("canvas.size", new CanvasSizeSetting()); + this.register("captcha.enable", new CaptchaEnableSetting()); + this.register("captcha.algorithm", new CaptchaAlgorithmSetting()); + this.register("captcha.maxnumber", new CaptchaMaxNumberSetting()); + } + + static get(): Settings; + static get(key?: T): ISettingValue; + static get(key?: T): ISettingValue | Settings { + if (typeof key === "string") { + return Settings.get().get(key); + } + + if (!this.instance) this.instance = new Settings(); + + return this.instance; + } + + static set(key: T, value: ISettingValue) { + return Settings.get().get(key, true).set(value); + } + + async initialize() { + await Promise.allSettled( + Object.values(this.settings).map((s) => + s.load(true).then(() => { + Logger.info("Loaded " + s.KEY); + }) + ) + ); + } + + register(key: T, instance: Setting) { + this.settings[key] = instance; + } + + get(key: T): ISettingValue; + get(key: T, full: true): Setting; + get( + key: T, + full?: boolean + ): ISettingValue | Setting { + if (!(key in this.settings)) { + throw new Error(`Failed to fetch setting ${key} as it's not registered`); + } + + if (full) { + // @ts-expect-error Generic type + return this.settings[key]; + } + + // @ts-expect-error generic type + return this.settings[key].get(); + } +} + +export class SettingNotSetError extends Error { + constructor(settingId: string) { + super("SettingNotSetError: Setting `" + settingId + "` is not set"); + } +} + +export class SettingStaleError extends Error { + constructor(settingId: string) { + super("SettingStaleError: Setting `" + settingId + "` is stale"); + } +} diff --git a/packages/server/src/settings/canvas/frozen.ts b/packages/server/src/settings/canvas/frozen.ts new file mode 100644 index 0000000000000000000000000000000000000000..21c1731a0000b45eb1c20f98af989d525f33f221 --- /dev/null +++ b/packages/server/src/settings/canvas/frozen.ts @@ -0,0 +1,9 @@ +import { Setting } from "../setting.class"; + +export class CanvasFrozenSetting extends Setting<"canvas.frozen"> { + readonly KEY = "canvas.frozen"; + + override default() { + return false; + } +} diff --git a/packages/server/src/settings/canvas/size.ts b/packages/server/src/settings/canvas/size.ts new file mode 100644 index 0000000000000000000000000000000000000000..68feb10801adbe47badc4c7141580d10757d5d9a --- /dev/null +++ b/packages/server/src/settings/canvas/size.ts @@ -0,0 +1,9 @@ +import { Setting } from "../setting.class"; + +export class CanvasSizeSetting extends Setting<"canvas.size"> { + readonly KEY = "canvas.size"; + + override default() { + return { width: 100, height: 100 }; + } +} diff --git a/packages/server/src/settings/captcha/algorithm.ts b/packages/server/src/settings/captcha/algorithm.ts new file mode 100644 index 0000000000000000000000000000000000000000..49113008fe670547448ad72554346d9bbf1a5bda --- /dev/null +++ b/packages/server/src/settings/captcha/algorithm.ts @@ -0,0 +1,9 @@ +import { ISettingValue, Setting } from "../setting.class"; + +export class CaptchaAlgorithmSetting extends Setting<"captcha.algorithm"> { + readonly KEY = "captcha.algorithm"; + + override default() { + return "SHA-256" as ISettingValue<"captcha.algorithm">; + } +} diff --git a/packages/server/src/settings/captcha/enable.ts b/packages/server/src/settings/captcha/enable.ts new file mode 100644 index 0000000000000000000000000000000000000000..92fe2e80d7fbf57b736f941942e630c6cfee3f1a --- /dev/null +++ b/packages/server/src/settings/captcha/enable.ts @@ -0,0 +1,9 @@ +import { Setting } from "../setting.class"; + +export class CaptchaEnableSetting extends Setting<"captcha.enable"> { + readonly KEY = "captcha.enable"; + + override default() { + return false; + } +} diff --git a/packages/server/src/settings/captcha/maxnumber.ts b/packages/server/src/settings/captcha/maxnumber.ts new file mode 100644 index 0000000000000000000000000000000000000000..117c8df6241d9c13c5e6063714eae1229934e13c --- /dev/null +++ b/packages/server/src/settings/captcha/maxnumber.ts @@ -0,0 +1,9 @@ +import { Setting } from "../setting.class"; + +export class CaptchaMaxNumberSetting extends Setting<"captcha.maxnumber"> { + readonly KEY = "captcha.maxnumber"; + + override default() { + return 1_000_000; + } +} diff --git a/packages/server/src/settings/setting.class.ts b/packages/server/src/settings/setting.class.ts new file mode 100644 index 0000000000000000000000000000000000000000..7679a63d107fb509fe7755b56073485d1bbaec5d --- /dev/null +++ b/packages/server/src/settings/setting.class.ts @@ -0,0 +1,79 @@ +import { prisma } from "../lib/prisma"; + +interface ISettings { + "canvas.frozen"(): boolean; + "canvas.size"(): { width: number; height: number }; + "captcha.enable"(): boolean; + "captcha.algorithm"(): "SHA-1" | "SHA-256" | "SHA-512"; + "captcha.maxnumber"(): number; +} + +export type ISettingValue = ReturnType< + ISettings[Key] +>; +export type ISettingKey = keyof ISettings; + +export abstract class Setting> { + abstract readonly KEY: K; + abstract default(): V; + + protected _staleFlag = true; + protected _value: V = this.default(); + protected _lastUpdated: Date | null = null; + + constructor() {} + + isStale() { + if (this._staleFlag) return true; + if (!this._lastUpdated) return true; + return Date.now() - this._lastUpdated.getTime() > 60 * 1000; + } + + async load(force?: boolean) { + if (!force && !this.isStale()) return this; + + const setting = await prisma.setting.findFirst({ + where: { + key: this.KEY, + }, + }); + + if (setting) { + this._value = JSON.parse(setting.value); + } + + this._lastUpdated = new Date(); + + return this; + } + + poke() { + this._staleFlag = true; + return this; + } + + get() { + if (this.isStale()) { + // if stale, update in the background + void this.load(); + } + + return this._value; + } + + async set(value: V) { + this._value = value; + await prisma.setting.upsert({ + where: { + key: this.KEY, + }, + create: { + key: this.KEY, + value: JSON.stringify(value), + }, + update: { + value: JSON.stringify(value), + }, + }); + } +} diff --git a/packages/server/src/tools/init_settings.ts b/packages/server/src/tools/init_settings.ts deleted file mode 100644 index b6afbb37d300e3340341fcae165d397ca51851d5..0000000000000000000000000000000000000000 --- a/packages/server/src/tools/init_settings.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { PrismaClient } from "@prisma/client"; - -const prisma = new PrismaClient(); - -// eslint-disable-next-line no-console -const log = (...msg: any[]) => console.log(...msg); - -async function main() { - const SETTINGS: { key: string; defaultValue: any }[] = [ - { - key: "canvas.size", - defaultValue: { - width: 100, - height: 100, - }, - }, - { - key: "canvas.frozen", - defaultValue: false, - }, - ]; - - for (const setting of SETTINGS) { - log("Ensuring setting", setting.key); - await prisma.setting.upsert({ - where: { key: setting.key }, - update: {}, - create: { - key: setting.key, - value: JSON.stringify(setting.defaultValue), - }, - }); - } -} - -main() - .then(async () => { - await prisma.$disconnect(); - }) - .catch(async (e) => { - // eslint-disable-next-line no-console - console.error(e); - await prisma.$disconnect(); - process.exit(1); - }); diff --git a/packages/server/src/types.ts b/packages/server/src/types.ts index e79e894ece36842333650fbd0fe9a01cdf1352d5..43cf8f38377f411c2faa23f3dea6877632f68b26 100644 --- a/packages/server/src/types.ts +++ b/packages/server/src/types.ts @@ -74,11 +74,8 @@ declare global { PIXEL_LOG_PATH?: string; - RECAPTCHA_SITE_KEY?: string; - RECAPTCHA_SECRET_KEY?: string; - RECAPTCHA_PIXEL_CHANCE?: string; - - DISCORD_WEBHOOK?: string; + CAPTCHA_HMAC_SECRET?: string; + CAPTCHA_HMAC_SECRET_FILE?: string; CACHE_WORKERS?: string; diff --git a/packages/server/src/utils/tryParseJSON.ts b/packages/server/src/utils/tryParseJSON.ts new file mode 100644 index 0000000000000000000000000000000000000000..6a2c0af09e7d4ade763c520a262b8ee7fffd39d3 --- /dev/null +++ b/packages/server/src/utils/tryParseJSON.ts @@ -0,0 +1,7 @@ +export const tryParseJSON = (input: string): T | null => { + try { + return JSON.parse(input); + } catch (_e) { + return null; + } +}; diff --git a/packages/server/src/utils/validate_environment.ts b/packages/server/src/utils/validate_environment.ts index 54510709743c924b60a091b1718bfadbeab2b037..a9d26e5c4cd107490c72816b9b4f90477ea14a92 100644 --- a/packages/server/src/utils/validate_environment.ts +++ b/packages/server/src/utils/validate_environment.ts @@ -1,3 +1,4 @@ +import { CaptchaController } from "../controllers/CaptchaController"; import { getLogger } from "../lib/Logger"; const Logger = getLogger("MAIN"); @@ -127,3 +128,5 @@ if (process.env.NODE_ENV !== "development" && process.env.DEV_ADMIN_TOKEN) { } // #endregion + +CaptchaController.validateEnvironment();