From 9b58708a1e8a1f085dd6d7670d3501a3079d9911 Mon Sep 17 00:00:00 2001 From: Medicopter117 Date: Fri, 13 Mar 2026 21:27:52 +0100 Subject: [PATCH 1/3] chore: Update Node.js dependencies and add a new Python requirements.txt file. --- package-lock.json | 1851 +++++++++++++++++++----------------------- package.json | 42 +- requirements/req.txt | 28 +- 3 files changed, 859 insertions(+), 1062 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0eef793..10b41fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,18 +42,18 @@ "cmdk": "1.1.1", "date-fns": "4.1.0", "embla-carousel-react": "8.6.0", - "framer-motion": "12.34.3", + "framer-motion": "12.36.0", "input-otp": "1.4.2", - "lucide-react": "0.575.0", + "lucide-react": "0.577.0", "next-themes": "0.4.6", "react": "19.2.4", - "react-day-picker": "9.13.2", + "react-day-picker": "9.14.0", "react-dom": "19.2.4", - "react-helmet-async": "^2.0.5", - "react-hook-form": "7.71.1", - "react-resizable-panels": "4.6.4", - "react-router-dom": "7.13.0", - "recharts": "3.7.0", + "react-helmet-async": "3.0.0", + "react-hook-form": "7.71.2", + "react-resizable-panels": "4.7.2", + "react-router-dom": "7.13.1", + "recharts": "3.8.0", "sonner": "2.0.7", "tailwind-merge": "3.5.0", "tailwindcss-animate": "1.0.7", @@ -62,26 +62,26 @@ }, "devDependencies": { "@eslint/js": "10.0.1", - "@tailwindcss/postcss": "^4.2.1", + "@tailwindcss/postcss": "4.2.1", "@tailwindcss/typography": "0.5.19", "@testing-library/jest-dom": "6.9.1", "@testing-library/react": "16.3.2", - "@types/node": "24.10.13", + "@types/node": "24.12.0", "@types/react": "19.2.14", "@types/react-dom": "19.2.3", - "@vitejs/plugin-react-swc": "4.2.3", - "autoprefixer": "10.4.24", - "eslint": "10.0.1", + "@vitejs/plugin-react-swc": "4.3.0", + "autoprefixer": "10.4.27", + "eslint": "10.0.3", "eslint-plugin-react-hooks": "7.0.1", - "eslint-plugin-react-refresh": "0.5.0", - "globals": "17.3.0", + "eslint-plugin-react-refresh": "0.5.2", + "globals": "17.4.0", "jsdom": "28.1.0", - "postcss": "8.5.6", - "tailwindcss": "4.2.0", + "postcss": "8.5.8", + "tailwindcss": "4.2.1", "typescript": "5.9.3", - "typescript-eslint": "8.56.0", - "vite": "7.3.1", - "vitest": "4.0.18" + "typescript-eslint": "8.57.0", + "vite": "8.0.0", + "vitest": "4.1.0" } }, "node_modules/@acemir/cssom": { @@ -587,446 +587,38 @@ "integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==", "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], + "node_modules/@emnapi/core": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.0.tgz", + "integrity": "sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@emnapi/wasi-threads": "1.2.0", + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], + "node_modules/@emnapi/runtime": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.0.tgz", + "integrity": "sha512-QN75eB0IH2ywSpRpNddCRfQIhmJYBCJ1x5Lb3IscKAL8bMnVAKnRg8dCoXbHzVLLH7P38N2Z3mtulB7W0J0FKw==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", + "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" + "dependencies": { + "tslib": "^2.4.0" } }, "node_modules/@eslint-community/eslint-utils": { @@ -1072,15 +664,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.2.tgz", - "integrity": "sha512-YF+fE6LV4v5MGWRGj7G404/OZzGNepVF8fxk7jqmqo3lrza7a0uUcDnROGRBG1WFC1omYUS/Wp1f42i0M+3Q3A==", + "version": "0.23.3", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz", + "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^3.0.2", + "@eslint/object-schema": "^3.0.3", "debug": "^4.3.1", - "minimatch": "^10.2.1" + "minimatch": "^10.2.4" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -1100,9 +692,9 @@ } }, "node_modules/@eslint/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.0.tgz", - "integrity": "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", + "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1134,9 +726,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.2.tgz", - "integrity": "sha512-HOy56KJt48Bx8KmJ+XGQNSUMT/6dZee/M54XyUyuvTvPXJmsERRvBchsUVx1UMe1WwIH49XLAczNC7V2INsuUw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", + "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1144,13 +736,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.0.tgz", - "integrity": "sha512-bIZEUzOI1jkhviX2cp5vNyXQc6olzb2ohewQubuYlMXZ2Q/XjBO0x0XhGPvc9fjSIiUN0vw+0hq53BJ4eQSJKQ==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", + "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^1.1.0", + "@eslint/core": "^1.1.1", "levn": "^0.4.1" }, "engines": { @@ -1327,6 +919,43 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz", + "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@oxc-project/runtime": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/runtime/-/runtime-0.115.0.tgz", + "integrity": "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.115.0.tgz", + "integrity": "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -3006,31 +2635,10 @@ "url": "https://opencollective.com/immer" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz", - "integrity": "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==", "cpu": [ "arm64" ], @@ -3039,12 +2647,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==", "cpu": [ "arm64" ], @@ -3053,12 +2664,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==", "cpu": [ "x64" ], @@ -3067,26 +2681,15 @@ "optional": true, "os": [ "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.9.tgz", + "integrity": "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==", "cpu": [ "x64" ], @@ -3095,26 +2698,15 @@ "optional": true, "os": [ "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", - "cpu": [ - "arm" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.9.tgz", + "integrity": "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==", "cpu": [ "arm" ], @@ -3123,26 +2715,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", - "cpu": [ - "arm64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==", "cpu": [ "arm64" ], @@ -3151,54 +2732,32 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", - "cpu": [ - "loong64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", - "cpu": [ - "ppc64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==", "cpu": [ "ppc64" ], @@ -3207,40 +2766,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", - "cpu": [ - "riscv64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==", "cpu": [ "s390x" ], @@ -3249,12 +2783,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.9.tgz", + "integrity": "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==", "cpu": [ "x64" ], @@ -3263,12 +2800,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.9.tgz", + "integrity": "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==", "cpu": [ "x64" ], @@ -3277,26 +2817,15 @@ "optional": true, "os": [ "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", - "cpu": [ - "x64" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.9.tgz", + "integrity": "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==", "cpu": [ "arm64" ], @@ -3305,40 +2834,49 @@ "optional": true, "os": [ "openharmony" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.9.tgz", + "integrity": "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==", "cpu": [ - "arm64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@napi-rs/wasm-runtime": "^1.1.1" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.9.tgz", + "integrity": "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==", "cpu": [ "x64" ], @@ -3347,21 +2885,17 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", - "cpu": [ - "x64" ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.7", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", + "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "license": "MIT" }, "node_modules/@standard-schema/spec": { "version": "1.1.0", @@ -3601,6 +3135,15 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@tabby_ai/hijri-converter": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@tabby_ai/hijri-converter/-/hijri-converter-1.0.5.tgz", + "integrity": "sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@tailwindcss/node": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", @@ -3617,13 +3160,6 @@ "tailwindcss": "4.2.1" } }, - "node_modules/@tailwindcss/node/node_modules/tailwindcss": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", - "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", - "dev": true, - "license": "MIT" - }, "node_modules/@tailwindcss/oxide": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", @@ -3831,6 +3367,70 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.8.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.8.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", @@ -3879,13 +3479,6 @@ "tailwindcss": "4.2.1" } }, - "node_modules/@tailwindcss/postcss/node_modules/tailwindcss": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", - "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", - "dev": true, - "license": "MIT" - }, "node_modules/@tailwindcss/typography": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", @@ -3973,6 +3566,17 @@ } } }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -4076,9 +3680,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.10.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", - "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", + "version": "24.12.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", + "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4112,17 +3716,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", - "integrity": "sha512-lRyPDLzNCuae71A3t9NEINBiTn7swyOhvUj3MyUOxb8x6g6vPEFoOU+ZRmGMusNC3X3YMhqMIX7i8ShqhT74Pw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz", + "integrity": "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.56.0", - "@typescript-eslint/type-utils": "8.56.0", - "@typescript-eslint/utils": "8.56.0", - "@typescript-eslint/visitor-keys": "8.56.0", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/type-utils": "8.57.0", + "@typescript-eslint/utils": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -4135,7 +3739,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.56.0", + "@typescript-eslint/parser": "^8.57.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -4151,16 +3755,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.0.tgz", - "integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.0.tgz", + "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.56.0", - "@typescript-eslint/types": "8.56.0", - "@typescript-eslint/typescript-estree": "8.56.0", - "@typescript-eslint/visitor-keys": "8.56.0", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3" }, "engines": { @@ -4176,14 +3780,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.0.tgz", - "integrity": "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", + "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.0", - "@typescript-eslint/types": "^8.56.0", + "@typescript-eslint/tsconfig-utils": "^8.57.0", + "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "engines": { @@ -4198,14 +3802,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.0.tgz", - "integrity": "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", + "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.0", - "@typescript-eslint/visitor-keys": "8.56.0" + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4216,9 +3820,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.0.tgz", - "integrity": "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", + "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", "dev": true, "license": "MIT", "engines": { @@ -4233,15 +3837,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.0.tgz", - "integrity": "sha512-qX2L3HWOU2nuDs6GzglBeuFXviDODreS58tLY/BALPC7iu3Fa+J7EOTwnX9PdNBxUI7Uh0ntP0YWGnxCkXzmfA==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz", + "integrity": "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.0", - "@typescript-eslint/typescript-estree": "8.56.0", - "@typescript-eslint/utils": "8.56.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/utils": "8.57.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -4258,9 +3862,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.0.tgz", - "integrity": "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", + "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", "dev": true, "license": "MIT", "engines": { @@ -4272,18 +3876,18 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.0.tgz", - "integrity": "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", + "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.56.0", - "@typescript-eslint/tsconfig-utils": "8.56.0", - "@typescript-eslint/types": "8.56.0", - "@typescript-eslint/visitor-keys": "8.56.0", + "@typescript-eslint/project-service": "8.57.0", + "@typescript-eslint/tsconfig-utils": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", - "minimatch": "^9.0.5", + "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" @@ -4299,43 +3903,17 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@typescript-eslint/utils": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.0.tgz", - "integrity": "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", + "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.0", - "@typescript-eslint/types": "8.56.0", - "@typescript-eslint/typescript-estree": "8.56.0" + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4350,13 +3928,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.0.tgz", - "integrity": "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", + "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.0", + "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -4368,34 +3946,34 @@ } }, "node_modules/@vitejs/plugin-react-swc": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.2.3.tgz", - "integrity": "sha512-QIluDil2prhY1gdA3GGwxZzTAmLdi8cQ2CcuMW4PB/Wu4e/1pzqrwhYWVd09LInCRlDUidQjd0B70QWbjWtLxA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-4.3.0.tgz", + "integrity": "sha512-mOkXCII839dHyAt/gpoSlm28JIVDwhZ6tnG6wJxUy2bmOx7UaPjvOyIDf3SFv5s7Eo7HVaq6kRcu6YMEzt5Z7w==", "dev": true, "license": "MIT", "dependencies": { - "@rolldown/pluginutils": "1.0.0-rc.2", + "@rolldown/pluginutils": "1.0.0-rc.7", "@swc/core": "^1.15.11" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4 || ^5 || ^6 || ^7" + "vite": "^4 || ^5 || ^6 || ^7 || ^8" } }, "node_modules/@vitest/expect": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", - "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.0.tgz", + "integrity": "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==", "dev": true, "license": "MIT", "dependencies": { - "@standard-schema/spec": "^1.0.0", + "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "chai": "^6.2.1", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "chai": "^6.2.2", "tinyrainbow": "^3.0.3" }, "funding": { @@ -4403,13 +3981,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", - "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.0.tgz", + "integrity": "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "4.0.18", + "@vitest/spy": "4.1.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, @@ -4418,7 +3996,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0-0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -4430,9 +4008,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", - "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.0.tgz", + "integrity": "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==", "dev": true, "license": "MIT", "dependencies": { @@ -4443,13 +4021,13 @@ } }, "node_modules/@vitest/runner": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", - "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.0.tgz", + "integrity": "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "4.0.18", + "@vitest/utils": "4.1.0", "pathe": "^2.0.3" }, "funding": { @@ -4457,13 +4035,14 @@ } }, "node_modules/@vitest/snapshot": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", - "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.0.tgz", + "integrity": "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "@vitest/utils": "4.1.0", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, @@ -4472,9 +4051,9 @@ } }, "node_modules/@vitest/spy": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", - "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.0.tgz", + "integrity": "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==", "dev": true, "license": "MIT", "funding": { @@ -4482,13 +4061,14 @@ } }, "node_modules/@vitest/utils": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", - "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.0.tgz", + "integrity": "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "4.0.18", + "@vitest/pretty-format": "4.1.0", + "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" }, "funding": { @@ -4529,9 +4109,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -4578,9 +4158,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.24", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz", - "integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==", + "version": "10.4.27", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", + "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", "dev": true, "funding": [ { @@ -4599,7 +4179,7 @@ "license": "MIT", "dependencies": { "browserslist": "^4.28.1", - "caniuse-lite": "^1.0.30001766", + "caniuse-lite": "^1.0.30001774", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -4614,13 +4194,6 @@ "postcss": "^8.1.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/baseline-browser-mapping": { "version": "2.9.15", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz", @@ -4642,26 +4215,26 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", - "integrity": "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/brace-expansion/node_modules/balanced-match": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", - "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" } }, "node_modules/browserslist": { @@ -4699,9 +4272,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001770", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", - "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", + "version": "1.0.30001778", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001778.tgz", + "integrity": "sha512-PN7uxFL+ExFJO61aVmP1aIEG4i9whQd4eoSCebav62UwDyp5OHh06zN4jqKSMePVgxHifCw1QJxdRkA1Pisekg==", "dev": true, "funding": [ { @@ -5153,9 +4726,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, @@ -5169,48 +4742,6 @@ "benchmarks" ] }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -5235,27 +4766,27 @@ } }, "node_modules/eslint": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.1.tgz", - "integrity": "sha512-20MV9SUdeN6Jd84xESsKhRly+/vxI+hwvpBMA93s+9dAcjdCuCojn4IqUGS3lvVaqjVYGYHSRMCpeFtF2rQYxQ==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", + "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", - "@eslint/config-array": "^0.23.2", + "@eslint/config-array": "^0.23.3", "@eslint/config-helpers": "^0.5.2", - "@eslint/core": "^1.1.0", - "@eslint/plugin-kit": "^0.6.0", + "@eslint/core": "^1.1.1", + "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^9.1.1", + "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.1.1", "esquery": "^1.7.0", @@ -5268,7 +4799,7 @@ "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "minimatch": "^10.2.1", + "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -5311,19 +4842,19 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.0.tgz", - "integrity": "sha512-ZYvmh7VfVgqR/7wR71I3Zl6hK/C5CcxdWYKZSpHawS5JCNgE4efhQWg/+/WPpgGAp9Ngp/rRZYyaIwmPQBq/lA==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz", + "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==", "dev": true, "license": "MIT", "peerDependencies": { - "eslint": ">=9" + "eslint": "^9 || ^10" } }, "node_modules/eslint-scope": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.1.tgz", - "integrity": "sha512-GaUN0sWim5qc8KVErfPBWmc31LEsOkrUJbvJZV+xuL3u2phMUK4HIvXlWAakfC8W4nzlK+chPEAkYOYb5ZScIw==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5547,13 +5078,13 @@ } }, "node_modules/framer-motion": { - "version": "12.34.3", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.34.3.tgz", - "integrity": "sha512-v81ecyZKYO/DfpTwHivqkxSUBzvceOpoI+wLfgCgoUIKxlFKEXdg0oR9imxwXumT4SFy8vRk9xzJ5l3/Du/55Q==", + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.36.0.tgz", + "integrity": "sha512-4PqYHAT7gev0ke0wos+PyrcFxI0HScjm3asgU8nSYa8YzJFuwgIvdj3/s3ZaxLq0bUSboIn19A2WS/MHwLCvfw==", "license": "MIT", "dependencies": { - "motion-dom": "^12.34.3", - "motion-utils": "^12.29.2", + "motion-dom": "^12.36.0", + "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { @@ -5621,9 +5152,9 @@ } }, "node_modules/globals": { - "version": "17.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz", - "integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==", + "version": "17.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz", + "integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==", "dev": true, "license": "MIT", "engines": { @@ -6231,9 +5762,9 @@ } }, "node_modules/lucide-react": { - "version": "0.575.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.575.0.tgz", - "integrity": "sha512-VuXgKZrk0uiDlWjGGXmKV6MSk9Yy4l10qgVvzGn2AWBx1Ylt0iBexKOAoA6I7JO3m+M9oeovJd3yYENfkUbOeg==", + "version": "0.577.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.577.0.tgz", + "integrity": "sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -6267,9 +5798,9 @@ } }, "node_modules/minimatch": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz", - "integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -6283,18 +5814,18 @@ } }, "node_modules/motion-dom": { - "version": "12.34.3", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.34.3.tgz", - "integrity": "sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ==", + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.36.0.tgz", + "integrity": "sha512-Ep1pq8P88rGJ75om8lTCA13zqd7ywPGwCqwuWwin6BKc0hMLkVfcS6qKlRqEo2+t0DwoUcgGJfXwaiFn4AOcQA==", "license": "MIT", "dependencies": { - "motion-utils": "^12.29.2" + "motion-utils": "^12.36.0" } }, "node_modules/motion-utils": { - "version": "12.29.2", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz", - "integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==", + "version": "12.36.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz", + "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==", "license": "MIT" }, "node_modules/ms": { @@ -6469,9 +6000,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, "funding": [ { @@ -6548,14 +6079,15 @@ } }, "node_modules/react-day-picker": { - "version": "9.13.2", - "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.13.2.tgz", - "integrity": "sha512-IMPiXfXVIAuR5Yk58DDPBC8QKClrhdXV+Tr/alBrwrHUw0qDDYB1m5zPNuTnnPIr/gmJ4ChMxmtqPdxm8+R4Eg==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.14.0.tgz", + "integrity": "sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==", "license": "MIT", "dependencies": { "@date-fns/tz": "^1.4.1", + "@tabby_ai/hijri-converter": "1.0.5", "date-fns": "^4.1.0", - "date-fns-jalali": "^4.1.0-0" + "date-fns-jalali": "4.1.0-0" }, "engines": { "node": ">=18" @@ -6587,9 +6119,9 @@ "license": "MIT" }, "node_modules/react-helmet-async": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz", - "integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-3.0.0.tgz", + "integrity": "sha512-nA3IEZfXiclgrz4KLxAhqJqIfFDuvzQwlKwpdmzZIuC1KNSghDEIXmyU0TKtbM+NafnkICcwx8CECFrZ/sL/1w==", "license": "Apache-2.0", "dependencies": { "invariant": "^2.2.4", @@ -6597,13 +6129,13 @@ "shallowequal": "^1.1.0" }, "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0" + "react": "^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/react-hook-form": { - "version": "7.71.1", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.1.tgz", - "integrity": "sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==", + "version": "7.71.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.2.tgz", + "integrity": "sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -6687,9 +6219,9 @@ } }, "node_modules/react-resizable-panels": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-4.6.4.tgz", - "integrity": "sha512-E7Szs1xyaMZ7xOI2gG4TECNz4r/gmpV1AsXyZRnER6OQnfFf9uclFmrHHZR3h/iF8vQS+nQ1LKyZv9bzwGxPSg==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-4.7.2.tgz", + "integrity": "sha512-1L2vyeBG96hp7N6x6rzYXJ8EjYiDiffMsqj3cd+T9aOKwscvuyCn2CuZ5q3PoUSTIJUM6Q5DgXH1bdDe6uvh2w==", "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -6697,9 +6229,9 @@ } }, "node_modules/react-router": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.0.tgz", - "integrity": "sha512-PZgus8ETambRT17BUm/LL8lX3Of+oiLaPuVTRH3l1eLvSPpKO3AvhAEb5N7ihAFZQrYDqkvvWfFh9p0z9VsjLw==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.13.1.tgz", + "integrity": "sha512-td+xP4X2/6BJvZoX6xw++A2DdEi++YypA69bJUV5oVvqf6/9/9nNlD70YO1e9d3MyamJEBQFEzk6mbfDYbqrSA==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -6719,12 +6251,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.0.tgz", - "integrity": "sha512-5CO/l5Yahi2SKC6rGZ+HDEjpjkGaG/ncEP7eWFTvFxbHP8yeeI0PxTDjimtpXYlR3b3i9/WIL4VJttPrESIf2g==", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.13.1.tgz", + "integrity": "sha512-UJnV3Rxc5TgUPJt2KJpo1Jpy0OKQr0AjgbZzBFjaPJcFOb2Y8jA5H3LT8HUJAiRLlWrEXWHbF1Z4SCZaQjWDHw==", "license": "MIT", "dependencies": { - "react-router": "7.13.0" + "react-router": "7.13.1" }, "engines": { "node": ">=20.0.0" @@ -6757,15 +6289,15 @@ } }, "node_modules/recharts": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.7.0.tgz", - "integrity": "sha512-l2VCsy3XXeraxIID9fx23eCb6iCBsxUQDnE8tWm6DFdszVAO7WVY/ChAD9wVit01y6B2PMupYiMmQwhgPHc9Ew==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.8.0.tgz", + "integrity": "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ==", "license": "MIT", "workspaces": [ "www" ], "dependencies": { - "@reduxjs/toolkit": "1.x.x || 2.x.x", + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", @@ -6831,50 +6363,46 @@ "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", "license": "MIT" }, - "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "node_modules/rolldown": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.9.tgz", + "integrity": "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@oxc-project/types": "=0.115.0", + "@rolldown/pluginutils": "1.0.0-rc.9" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", - "fsevents": "~2.3.2" - } + "@rolldown/binding-android-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", + "@rolldown/binding-darwin-x64": "1.0.0-rc.9", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" + } + }, + "node_modules/rolldown/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.9", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.9.tgz", + "integrity": "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==", + "dev": true, + "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", @@ -6978,9 +6506,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, @@ -7015,9 +6543,9 @@ } }, "node_modules/tailwindcss": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.0.tgz", - "integrity": "sha512-yYzTZ4++b7fNYxFfpnberEEKu43w44aqDMNM9MHMmcKuCH7lL8jJ4yJ7LGHv7rSwiqM0nkiobF9I6cLlpS2P7Q==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", "dev": true, "license": "MIT" }, @@ -7187,16 +6715,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.56.0.tgz", - "integrity": "sha512-c7toRLrotJ9oixgdW7liukZpsnq5CZ7PuKztubGYlNppuTqhIoWfhgHo/7EU0v06gS2l/x0i2NEFK1qMIf0rIg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.57.0.tgz", + "integrity": "sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.56.0", - "@typescript-eslint/parser": "8.56.0", - "@typescript-eslint/typescript-estree": "8.56.0", - "@typescript-eslint/utils": "8.56.0" + "@typescript-eslint/eslint-plugin": "8.57.0", + "@typescript-eslint/parser": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/utils": "8.57.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -7363,17 +6891,17 @@ } }, "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.0.tgz", + "integrity": "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", + "@oxc-project/runtime": "0.115.0", + "lightningcss": "^1.32.0", "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", + "postcss": "^8.5.8", + "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "bin": { @@ -7390,9 +6918,10 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.0.0-alpha.31", + "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", - "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", @@ -7405,13 +6934,16 @@ "@types/node": { "optional": true }, - "jiti": { + "@vitejs/devtools": { "optional": true }, - "less": { + "esbuild": { + "optional": true + }, + "jiti": { "optional": true }, - "lightningcss": { + "less": { "optional": true }, "sass": { @@ -7437,32 +6969,293 @@ } } }, + "node_modules/vite/node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/vite/node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/vitest": { - "version": "4.0.18", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", - "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.0.tgz", + "integrity": "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "4.0.18", - "@vitest/mocker": "4.0.18", - "@vitest/pretty-format": "4.0.18", - "@vitest/runner": "4.0.18", - "@vitest/snapshot": "4.0.18", - "@vitest/spy": "4.0.18", - "@vitest/utils": "4.0.18", - "es-module-lexer": "^1.7.0", - "expect-type": "^1.2.2", + "@vitest/expect": "4.1.0", + "@vitest/mocker": "4.1.0", + "@vitest/pretty-format": "4.1.0", + "@vitest/runner": "4.1.0", + "@vitest/snapshot": "4.1.0", + "@vitest/spy": "4.1.0", + "@vitest/utils": "4.1.0", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", - "std-env": "^3.10.0", + "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", - "vite": "^6.0.0 || ^7.0.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "bin": { @@ -7478,12 +7271,13 @@ "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.0.18", - "@vitest/browser-preview": "4.0.18", - "@vitest/browser-webdriverio": "4.0.18", - "@vitest/ui": "4.0.18", + "@vitest/browser-playwright": "4.1.0", + "@vitest/browser-preview": "4.1.0", + "@vitest/browser-webdriverio": "4.1.0", + "@vitest/ui": "4.1.0", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { @@ -7512,6 +7306,9 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, @@ -7666,4 +7463,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index d577d08..e7b314c 100644 --- a/package.json +++ b/package.json @@ -47,18 +47,18 @@ "cmdk": "1.1.1", "date-fns": "4.1.0", "embla-carousel-react": "8.6.0", - "framer-motion": "12.34.3", + "framer-motion": "12.36.0", "input-otp": "1.4.2", - "lucide-react": "0.575.0", + "lucide-react": "0.577.0", "next-themes": "0.4.6", "react": "19.2.4", - "react-day-picker": "9.13.2", + "react-day-picker": "9.14.0", "react-dom": "19.2.4", - "react-helmet-async": "^2.0.5", - "react-hook-form": "7.71.1", - "react-resizable-panels": "4.6.4", - "react-router-dom": "7.13.0", - "recharts": "3.7.0", + "react-helmet-async": "3.0.0", + "react-hook-form": "7.71.2", + "react-resizable-panels": "4.7.2", + "react-router-dom": "7.13.1", + "recharts": "3.8.0", "sonner": "2.0.7", "tailwind-merge": "3.5.0", "tailwindcss-animate": "1.0.7", @@ -67,25 +67,25 @@ }, "devDependencies": { "@eslint/js": "10.0.1", - "@tailwindcss/postcss": "^4.2.1", + "@tailwindcss/postcss": "4.2.1", "@tailwindcss/typography": "0.5.19", "@testing-library/jest-dom": "6.9.1", "@testing-library/react": "16.3.2", - "@types/node": "24.10.13", + "@types/node": "24.12.0", "@types/react": "19.2.14", "@types/react-dom": "19.2.3", - "@vitejs/plugin-react-swc": "4.2.3", - "autoprefixer": "10.4.24", - "eslint": "10.0.1", + "@vitejs/plugin-react-swc": "4.3.0", + "autoprefixer": "10.4.27", + "eslint": "10.0.3", "eslint-plugin-react-hooks": "7.0.1", - "eslint-plugin-react-refresh": "0.5.0", - "globals": "17.3.0", + "eslint-plugin-react-refresh": "0.5.2", + "globals": "17.4.0", "jsdom": "28.1.0", - "postcss": "8.5.6", - "tailwindcss": "4.2.0", + "postcss": "8.5.8", + "tailwindcss": "4.2.1", "typescript": "5.9.3", - "typescript-eslint": "8.56.0", - "vite": "7.3.1", - "vitest": "4.0.18" + "typescript-eslint": "8.57.0", + "vite": "8.0.0", + "vitest": "4.1.0" } -} +} \ No newline at end of file diff --git a/requirements/req.txt b/requirements/req.txt index feef944..b1455aa 100644 --- a/requirements/req.txt +++ b/requirements/req.txt @@ -1,13 +1,13 @@ # --- Deine Online Packages (ManagerX Ecosystem) --- -ManagerX-DevTools==1.2026.1.11.1 -ManagerX-Handler==1.2026.1.10 +ManagerX-DevTools==1.2026.2.26 +ManagerX-Handler==1.2026.2.9.4 # --- Core Frameworks & Discord --- ezcord==0.7.4 -py-cord==2.7.0 +py-cord==2.7.1 better-ipc==2.0.3 -fastapi==0.128.4 -uvicorn==0.40.0 +fastapi==0.135.1 +uvicorn==0.41.0 starlette==0.52.1 # --- Async & Performance --- @@ -26,7 +26,7 @@ websockets==16.0 # --- Data & Validation --- annotated-types==0.7.0 pydantic==2.12.5 -pydantic_core==2.41.5 +pydantic_core==2.42.0 PyYAML==6.0.3 typing_extensions==4.15.0 typing-inspection==0.4.2 @@ -38,9 +38,9 @@ httpx==0.28.1 httpcore==1.0.9 h11==0.16.0 urllib3==2.6.3 -yarl==1.22.0 -certifi==2026.1.4 -charset-normalizer==3.4.4 +yarl==1.23.0 +certifi==2026.2.25 +charset-normalizer==3.4.5 idna==3.11 rfc3986==2.0.0 @@ -48,10 +48,10 @@ rfc3986==2.0.0 beautifulsoup4==4.14.3 soupsieve==2.8.3 easy-pil==0.4.0 -pillow==12.1.0 +pillow==12.1.1 SimpleColoredLogs==1.16.1.2026 colorama==0.4.6 -rich==14.3.2 +rich==14.3.3 Pygments==2.19.2 markdown-it-py==4.0.0 mdurl==0.1.2 @@ -59,9 +59,9 @@ mdurl==0.1.2 # --- System & Utilities --- click==8.3.1 psutil==7.2.2 -python-dotenv==1.2.1 +python-dotenv==1.2.2 timedelta==2020.12.3 -pytz==2025.2 +pytz==2026.1.post1 DateTime==6.0 six==1.17.0 cffi==2.0.0 @@ -79,7 +79,7 @@ packaging==26.0 pathlib==1.0.1 more-itertools==10.8.0 jaraco.classes==3.4.0 -jaraco.context==6.1.0 +jaraco.context==6.1.1 jaraco.functools==4.4.0 docutils==0.22.4 nh3==0.3.2Ne \ No newline at end of file From 6cf401e06ea5be40e76a0df9de4af61b6628f61f Mon Sep 17 00:00:00 2001 From: Medicopter117 Date: Sun, 15 Mar 2026 14:45:48 +0100 Subject: [PATCH 2/3] feat: Implement a new web dashboard with dedicated settings components, API routes, and new bot cogs. --- README.md | 4 + docs/source/_static/custom.css | 64 ++-- main.py | 11 +- package.json | 1 - pyproject.toml | 2 +- src/api/dashboard/auth_routes.py | 169 ++++++++++ src/api/dashboard/routes.py | 144 +++++++- src/api/dashboard/settings_routes.py | 354 ++++++++++++++++++++ src/bot/cogs/guild/globalchat.py | 2 +- src/bot/cogs/guild/welcome.py | 1 + src/bot/cogs/management/autodelete.py | 2 +- src/bot/cogs/user/stats.py | 1 + src/bot/core/__init__.py | 1 - src/{bot/core => scripts}/constants.py | 0 src/web/App.tsx | 65 +++- src/web/components/AntiSpamSettings.tsx | 186 ++++++++++ src/web/components/AuthProvider.tsx | 112 +++++++ src/web/components/AutoDeleteSettings.tsx | 202 +++++++++++ src/web/components/AutoRoleSettings.tsx | 197 +++++++++++ src/web/components/GlobalChatSettings.tsx | 188 +++++++++++ src/web/components/GuildSelector.tsx | 79 +++++ src/web/components/LevelSettings.tsx | 245 ++++++++++++++ src/web/components/LoggingSettings.tsx | 233 +++++++++++++ src/web/components/Navbar.tsx | 46 ++- src/web/components/OverviewCharts.tsx | 98 ++++++ src/web/components/OverviewSettings.tsx | 143 ++++++++ src/web/components/WelcomeSettings.tsx | 276 +++++++++++++++ src/web/components/ui/chart.tsx | 303 ----------------- src/web/dashboard/LoginPage.tsx | 215 ++++++++++++ src/web/dashboard/SettingsPage.tsx | 391 ++++++++++++++++++++++ src/web/pages/AuthCallback.tsx | 86 +++++ src/web/pages/Impressum.tsx | 2 +- 32 files changed, 3470 insertions(+), 353 deletions(-) create mode 100644 src/api/dashboard/auth_routes.py create mode 100644 src/api/dashboard/settings_routes.py rename src/{bot/core => scripts}/constants.py (100%) create mode 100644 src/web/components/AntiSpamSettings.tsx create mode 100644 src/web/components/AuthProvider.tsx create mode 100644 src/web/components/AutoDeleteSettings.tsx create mode 100644 src/web/components/AutoRoleSettings.tsx create mode 100644 src/web/components/GlobalChatSettings.tsx create mode 100644 src/web/components/GuildSelector.tsx create mode 100644 src/web/components/LevelSettings.tsx create mode 100644 src/web/components/LoggingSettings.tsx create mode 100644 src/web/components/OverviewCharts.tsx create mode 100644 src/web/components/OverviewSettings.tsx create mode 100644 src/web/components/WelcomeSettings.tsx delete mode 100644 src/web/components/ui/chart.tsx create mode 100644 src/web/dashboard/LoginPage.tsx create mode 100644 src/web/dashboard/SettingsPage.tsx create mode 100644 src/web/pages/AuthCallback.tsx diff --git a/README.md b/README.md index 8e8e4e4..56c2f57 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,10 @@ **Entwickelt von** [**ManagerX Development**](https://github.com/ManagerX-Development) **|** ⚡ **Powered by OPPRO.NET Network™** + +Webseite: https://managerx-bot.de +Dokumentation: https://docs.managerx-bot.de +API: https://api.managerx-bot.de

diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css index 4b4c030..1aea4b3 100644 --- a/docs/source/_static/custom.css +++ b/docs/source/_static/custom.css @@ -3,8 +3,6 @@ PyData Sphinx Theme - Optimized & Refined ========================================================================== */ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap'); - :root { /* ManagerX Premium Color System */ --mx-red-primary: #dc2626; @@ -13,7 +11,7 @@ --mx-red-light: #fef2f2; --mx-red-accent: #f87171; --mx-red-glow: rgba(220, 38, 38, 0.1); - + /* Neutral Palette */ --mx-gray-50: #f8fafc; --mx-gray-100: #f1f5f9; @@ -25,37 +23,37 @@ --mx-gray-700: #334155; --mx-gray-800: #1e293b; --mx-gray-900: #0f172a; - + /* Semantic Colors */ --mx-success: #059669; --mx-warning: #d97706; --mx-danger: #dc2626; --mx-info: #0284c7; - + /* Typography System */ --pst-font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --pst-font-family-heading: 'Space Grotesk', 'Inter', sans-serif; --pst-font-family-monospace: 'JetBrains Mono', 'Consolas', 'Monaco', monospace; - + /* PyData Theme Overrides */ --pst-color-primary: var(--mx-red-primary); --pst-color-secondary: var(--mx-gray-600); --pst-color-link: var(--mx-red-primary); --pst-color-link-hover: var(--mx-red-dark); --pst-color-target: #fbbf24; - + /* Shadows & Effects */ --mx-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.05); --mx-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.06); --mx-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08); --mx-shadow-lg: 0 10px 24px rgba(0, 0, 0, 0.1); --mx-shadow-xl: 0 20px 40px rgba(0, 0, 0, 0.12); - + /* Transitions */ --mx-transition-fast: 0.15s cubic-bezier(0.4, 0, 0.2, 1); --mx-transition-base: 0.25s cubic-bezier(0.4, 0, 0.2, 1); --mx-transition-slow: 0.4s cubic-bezier(0.4, 0, 0.2, 1); - + /* Border Radius */ --mx-radius-sm: 6px; --mx-radius-md: 10px; @@ -107,7 +105,12 @@ body { } /* Improved Typography Hierarchy */ -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { font-family: var(--pst-font-family-heading); font-weight: 700; letter-spacing: -0.025em; @@ -255,8 +258,8 @@ h2::before { } /* Active Navigation Item */ -.bd-sidebar-primary .nav-item.current > a, -.bd-sidebar-primary .nav-item.active > a { +.bd-sidebar-primary .nav-item.current>a, +.bd-sidebar-primary .nav-item.active>a { background: linear-gradient(90deg, var(--mx-red-light) 0%, transparent 100%); color: var(--mx-red-primary) !important; font-weight: 600; @@ -264,7 +267,7 @@ h2::before { padding-left: calc(1rem - 3px); } -[data-theme="dark"] .bd-sidebar-primary .nav-item.current > a { +[data-theme="dark"] .bd-sidebar-primary .nav-item.current>a { background: linear-gradient(90deg, rgba(220, 38, 38, 0.15) 0%, transparent 100%); } @@ -301,10 +304,13 @@ article p { } @keyframes highlight-pulse { - 0%, 50% { + + 0%, + 50% { background-color: var(--mx-red-glow); box-shadow: 0 0 0 8px var(--mx-red-glow); } + 100% { background-color: transparent; box-shadow: 0 0 0 0 transparent; @@ -861,11 +867,9 @@ dt.sig { .mx-hero { text-align: center; padding: 5rem 2rem; - background: radial-gradient( - circle at center, - var(--mx-red-glow) 0%, - transparent 70% - ); + background: radial-gradient(circle at center, + var(--mx-red-glow) 0%, + transparent 70%); border-radius: var(--mx-radius-xl); margin: 3rem 0; } @@ -950,19 +954,19 @@ dt.sig { h1 { font-size: 2rem; } - + h2 { font-size: 1.65rem; } - + h3 { font-size: 1.35rem; } - + .bd-main { padding-top: 1rem; } - + .mx-hero { padding: 3rem 1.5rem; } @@ -972,19 +976,19 @@ dt.sig { h1 { font-size: 1.75rem; } - + h2 { font-size: 1.5rem; } - + .admonition { padding: 1.25rem !important; } - + table.docutils { font-size: 0.85rem; } - + .prev-next-area a { padding: 1.25rem !important; } @@ -995,6 +999,7 @@ dt.sig { ========================================================================== */ @media print { + .bd-header, .bd-sidebar-primary, .bd-sidebar-secondary, @@ -1002,11 +1007,11 @@ dt.sig { .prev-next-area { display: none !important; } - + article { max-width: 100% !important; } - + .admonition { page-break-inside: avoid; } @@ -1044,6 +1049,7 @@ input:focus-visible { /* Reduced Motion */ @media (prefers-reduced-motion: reduce) { + *, *::before, *::after { diff --git a/main.py b/main.py index dd2dc30..3dc2ddc 100644 --- a/main.py +++ b/main.py @@ -25,6 +25,12 @@ # Logger (muss existieren!) from logger import logger +# ============================================================================= +# SETUP +# ============================================================================= +BASEDIR = Path(__file__).resolve().parent +load_dotenv(dotenv_path=BASEDIR / 'config' / '.env') + # Lokale Module aus src/bot/core from src.bot.core.config import ConfigLoader, BotConfig from src.bot.core.bot_setup import BotSetup @@ -37,11 +43,6 @@ from src.api.dashboard.routes import set_bot_instance, router as dashboard_router from mx_handler import TranslationHandler -# ============================================================================= -# SETUP -# ============================================================================= -BASEDIR = Path(__file__).resolve().parent -load_dotenv(dotenv_path=BASEDIR / 'config' / '.env') colorama_init(autoreset=True) TranslationHandler.settings( diff --git a/package.json b/package.json index e7b314c..56be7e0 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,6 @@ "react-hook-form": "7.71.2", "react-resizable-panels": "4.7.2", "react-router-dom": "7.13.1", - "recharts": "3.8.0", "sonner": "2.0.7", "tailwind-merge": "3.5.0", "tailwindcss-animate": "1.0.7", diff --git a/pyproject.toml b/pyproject.toml index b2083c4..ceb149d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ManagerX" -version = "2.0.0+build29cbfd2" +version = "2.0.0+build9b58708" description = "A powerful Discord bot for server management and fun." readme = "README.md" requires-python = ">=3.8" diff --git a/src/api/dashboard/auth_routes.py b/src/api/dashboard/auth_routes.py new file mode 100644 index 0000000..e5dec6a --- /dev/null +++ b/src/api/dashboard/auth_routes.py @@ -0,0 +1,169 @@ +from fastapi import APIRouter, Request, HTTPException, Security, status, Depends +from fastapi.responses import RedirectResponse +import httpx +import jwt +import os +import time +from urllib.parse import urlencode + +router = APIRouter( + prefix="/auth", + tags=["auth"] +) + +# JWT Setup +JWT_SECRET = os.getenv("JWT_SECRET", "fallback-secret") +ALGORITHM = "HS256" +ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 7 days + +# Discord OAuth Setup +CLIENT_ID = os.getenv("DISCORD_CLIENT_ID") +CLIENT_SECRET = os.getenv("DISCORD_CLIENT_SECRET") +REDIRECT_URI = os.getenv("DISCORD_REDIRECT_URI", "http://localhost:8080/dash/auth/callback") +DASHBOARD_URL = os.getenv("DASHBOARD_URL", "http://localhost:8080") + +# We import bot_instance dynamically or keep a local ref if passed +# Removed top level import to prevent circular import + +def create_access_token(data: dict): + to_encode = data.copy() + expire = time.time() + (ACCESS_TOKEN_EXPIRE_MINUTES * 60) + to_encode.update({"exp": expire}) + encoded_jwt = jwt.encode(to_encode, JWT_SECRET, algorithm=ALGORITHM) + return encoded_jwt + +def get_current_user(request: Request): + """Dependency to get the current user from the Authorization header.""" + auth_header = request.headers.get("Authorization") + if not auth_header or not auth_header.startswith("Bearer "): + raise HTTPException(status_code=401, detail="Not authenticated") + + token = auth_header.split(" ")[1] + + try: + payload = jwt.decode(token, JWT_SECRET, algorithms=[ALGORITHM]) + user_id: str = payload.get("sub") + if user_id is None: + raise HTTPException(status_code=401, detail="Invalid token") + return {"id": user_id, "username": payload.get("username", ""), "avatar": payload.get("avatar", "")} + except jwt.ExpiredSignatureError: + raise HTTPException(status_code=401, detail="Token has expired") + except jwt.InvalidTokenError: + raise HTTPException(status_code=401, detail="Invalid token") + +@router.get("/login") +async def login(): + """Generates the Discord OAuth2 Authorization URL and redirects the user.""" + # We want to respond to the dashboard frontend, passing the code back to the frontend. + params = { + "client_id": CLIENT_ID, + "redirect_uri": REDIRECT_URI, + "response_type": "code", + "scope": "identify guilds", + "prompt": "consent" + } + url = f"https://discord.com/oauth2/authorize?{urlencode(params)}" + print(f"[DEBUG] Generated Discord URL: {url}") + return {"url": url} + +@router.post("/callback") +async def callback(request: Request): + """Exchanges code for a token and creates a JWT session.""" + data = await request.json() + code = data.get("code") + + if not code: + raise HTTPException(status_code=400, detail="No code provided") + + # Exchange code for token + async with httpx.AsyncClient() as client: + token_data = { + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "grant_type": "authorization_code", + "code": code, + "redirect_uri": REDIRECT_URI + } + + headers = { + "Content-Type": "application/x-www-form-urlencoded" + } + + try: + token_res = await client.post("https://discord.com/api/oauth2/token", data=token_data, headers=headers) + token_res.raise_for_status() + token_json = token_res.json() + access_token = token_json.get("access_token") + except Exception as e: + raise HTTPException(status_code=400, detail=f"Failed to exchange token: {e}") + + # Get user info + user_res = await client.get("https://discord.com/api/users/@me", headers={ + "Authorization": f"Bearer {access_token}" + }) + user_json = user_res.json() + user_id = user_json.get("id") + + # Verify if user has admin permissions on any guild bot is in (we handle actual guilds in /me) + # For now, just generate JWT + jwt_token = create_access_token({ + "sub": user_id, + "username": user_json.get("username"), + "avatar": user_json.get("avatar") + }) + + return { + "access_token": jwt_token, + "token_type": "bearer", + "user": { + "id": str(user_id), + "username": user_json.get("username"), + "avatar": user_json.get("avatar") + }, + "discord_token": access_token # Send discord token to frontend to fetch guilds + } + +@router.get("/me") +async def get_me(request: Request, user: dict = Depends(get_current_user)): + """Returns the user along with guilds they manage that the bot is also in.""" + from src.api.dashboard.routes import bot_instance + + auth_header = request.headers.get("Authorization") + if not auth_header: + raise HTTPException(status_code=401) + + # In a real app, we'd store the Discord Access Token in a session or database. + # For now, let's assume the client might send it or we fetch it if we had it. + # To make this "really work" without a DB yet, we expect a 'X-Discord-Token' header + # or just use the one from the callback if we were to store it. + + discord_token = request.headers.get("X-Discord-Token") + user_guilds = [] + + if discord_token: + async with httpx.AsyncClient() as client: + guilds_res = await client.get("https://discord.com/api/users/@me/guilds", headers={ + "Authorization": f"Bearer {discord_token}" + }) + if guilds_res.status_code == 200: + all_guilds = guilds_res.json() + for g in all_guilds: + # check permissions (Manage Guild = 0x20) + perms = int(g.get("permissions", 0)) + is_admin = (perms & 0x20) == 0x20 or (perms & 0x8) == 0x8 + + if is_admin: + # Check if bot is in guild + guild_id = int(g.get("id")) + if bot_instance and bot_instance.get_guild(guild_id): + user_guilds.append({ + "id": str(guild_id), + "name": g.get("name"), + "icon": g.get("icon"), + "permissions": perms + }) + + return { + "user": user, + "guilds": user_guilds + } diff --git a/src/api/dashboard/routes.py b/src/api/dashboard/routes.py index a4f3b5a..adc4c9c 100644 --- a/src/api/dashboard/routes.py +++ b/src/api/dashboard/routes.py @@ -1,11 +1,16 @@ -from fastapi import APIRouter, Request, HTTPException, Security, status +from fastapi import APIRouter, Request, HTTPException, Security, status, Depends from fastapi.security import APIKeyHeader import os +import discord +from src.api.dashboard.auth_routes import get_current_user from typing import List, Optional from datetime import datetime import time # Falls du Schemas nutzt: from .schemas import ServerStatus, UserInfo +from .auth_routes import router as auth_router +from .settings_routes import router as settings_router + # Wir erstellen einen Router, den wir später in die Haupt-App einbinden router_public = APIRouter( prefix="/v1/managerx", @@ -93,8 +98,141 @@ async def get_api_key(api_key_header: str = Security(API_KEY_HEADER)): router = APIRouter( prefix="/dashboard", - tags=["dashboard"], - dependencies=[Security(get_api_key)] + tags=["dashboard"] ) + +# Public sub-routers (no global X-API-KEY required, they manage their own like JWT) +@router.get("/guilds/{guild_id}/channels") +async def get_guild_channels(guild_id: int, user: dict = Depends(get_current_user)): + """Fetches text channels for a specific guild.""" + if bot_instance is None: + raise HTTPException(status_code=503, detail="Bot-Verbindung nicht verfügbar") + + guild = bot_instance.get_guild(guild_id) + if not guild: + raise HTTPException(status_code=404, detail="Guild not found or bot not in guild") + + # Check if user is in guild and has appropriate permissions (Manage Guild or Admin) + member = guild.get_member(int(user["id"])) + if not member or not (member.guild_permissions.manage_guild or member.guild_permissions.administrator): + raise HTTPException(status_code=403, detail="Insufficient permissions") + + channels = [ + {"id": str(c.id), "name": c.name} + for c in guild.text_channels + ] + return {"channels": channels} + +@router.get("/guilds/{guild_id}/roles") +async def get_guild_roles(guild_id: int, user: dict = Depends(get_current_user)): + """Fetches manageable roles for a specific guild.""" + if bot_instance is None: + raise HTTPException(status_code=503, detail="Bot-Verbindung nicht verfügbar") + + guild = bot_instance.get_guild(guild_id) + if not guild: + raise HTTPException(status_code=404, detail="Guild not found or bot not in guild") + + member = guild.get_member(int(user["id"])) + if not member or not (member.guild_permissions.manage_guild or member.guild_permissions.administrator): + raise HTTPException(status_code=403, detail="Insufficient permissions") + + roles = [ + {"id": str(r.id), "name": r.name, "color": str(r.color)} + for r in guild.roles if not r.is_default() and not r.managed + ] + return {"roles": roles} + +@router.get("/guilds/{guild_id}/stats") +async def get_guild_stats(guild_id: int, user: dict = Depends(get_current_user)): + """Fetches server statistics (Daily joins, message count, member total).""" + if bot_instance is None: + raise HTTPException(status_code=503, detail="Bot-Verbindung nicht verfügbar") + + guild = bot_instance.get_guild(guild_id) + if not guild: + raise HTTPException(status_code=404, detail="Guild not found or bot not in guild") + + member = guild.get_member(int(user["id"])) + if not member or not (member.guild_permissions.manage_guild or member.guild_permissions.administrator): + raise HTTPException(status_code=403, detail="Insufficient permissions") + + # Fetch daily growth/activity + today_str = datetime.now().strftime('%Y-%m-%d') + joined_today = 0 + messages_today = 0 + history = [] + + try: + # Pre-fetch histories + welcome_history = [] + stats_history = [] + + if hasattr(bot_instance, 'welcome_db'): + welcome_history = await bot_instance.welcome_db.get_weekly_stats(guild_id) + for day in welcome_history: + if day['date'] == today_str: + joined_today = day['joins'] + + if hasattr(bot_instance, 'stats_db'): + messages_today = await bot_instance.stats_db.get_daily_messages(guild_id, today_str) + stats_history = await bot_instance.stats_db.get_weekly_stats(guild_id) + + # 2. Combine history for the last 7 days + for i in range(6, -1, -1): + date_obj = datetime.now() - timedelta(days=i) + d_str = date_obj.strftime('%Y-%m-%d') + day_name = date_obj.strftime('%a') + + m_count = 0 + j_count = 0 + + # Find in pre-fetched histories + for h in stats_history: + if h['date'] == d_str: + m_count = h['messages'] + break + + for h in welcome_history: + if h['date'] == d_str: + j_count = h['joins'] + break + + history.append({ + "name": day_name, + "messages": m_count, + "joins": j_count + }) + + # Prepare final stats object + total_members = guild.member_count or len(guild.members) + online_members = 0 + if intents_working := guild.members: + online_members = sum(1 for m in guild.members if m.status != discord.Status.offline) + + stats = { + "total_members": total_members, + "online_members": online_members, + "text_channels": len(guild.text_channels), + "voice_channels": len(guild.voice_channels), + "joined_today": joined_today, + "messages_today": messages_today, + "history": history + } + + return stats + except Exception as e: + print(f"Stats error: {e}") + return { + "total_members": guild.member_count, + "online_members": 0, + "text_channels": len(guild.text_channels), + "voice_channels": len(guild.voice_channels), + "joined_today": 0, + "messages_today": 0 + } + +router.include_router(auth_router) +router.include_router(settings_router) router.include_router(router_public) diff --git a/src/api/dashboard/settings_routes.py b/src/api/dashboard/settings_routes.py new file mode 100644 index 0000000..d054acc --- /dev/null +++ b/src/api/dashboard/settings_routes.py @@ -0,0 +1,354 @@ +from fastapi import APIRouter, Request, HTTPException, Security, status, Depends +from src.api.dashboard.auth_routes import get_current_user +from mx_devtools import WelcomeDatabase, AntiSpamDatabase, GlobalChatDatabase, LevelDatabase, LoggingDatabase, AutoDeleteDB, AutoRoleDatabase +import discord +from datetime import datetime + +router = APIRouter( + prefix="/settings", + tags=["settings"], + dependencies=[Depends(get_current_user)] +) + +async def send_dashboard_notification(guild_id: int, module_name: str, user_name: str, channel_id: int = None): + """Helper to send a notification to a Discord channel when settings are saved.""" + from src.api.dashboard.routes import bot_instance + if not bot_instance: + return + + guild = bot_instance.get_guild(guild_id) + if not guild: + return + + # Try to find a suitable channel if none provided + if not channel_id: + # For general settings, we might use a system channel or first available + target_channel = guild.system_channel or guild.text_channels[0] + else: + target_channel = guild.get_channel(channel_id) + + if not target_channel: + return + + embed = discord.Embed( + title="⚙️ Dashboard Einstellungen aktualisiert", + description=f"Die Einstellungen für das Modul **{module_name}** wurden über das Dashboard geändert.", + color=discord.Color.blue(), + timestamp=datetime.now() + ) + embed.add_field(name="Administrator", value=user_name, inline=True) + embed.add_field(name="Modul", value=module_name, inline=True) + embed.set_footer(text="ManagerX Dashboard System", icon_url=bot_instance.user.avatar.url if bot_instance.user.avatar else None) + + try: + await target_channel.send(embed=embed) + except Exception as e: + print(f"Failed to send dashboard notification: {e}") + +@router.get("/{guild_id}") +async def get_settings(guild_id: int): + """Fetch settings for a specific guild.""" + from src.api.dashboard.routes import bot_instance + + if not bot_instance or not hasattr(bot_instance, 'settings_db'): + raise HTTPException(status_code=503, detail="Bot database not ready") + + try: + guild_lang = bot_instance.settings_db.get_guild_language(guild_id) if hasattr(bot_instance.settings_db, 'get_guild_language') else "de" + + return { + "success": True, + "data": { + "bot_name": bot_instance.user.name, + "prefix": "!" , + "auto_mod": True, + "welcome_message": False, + "language": guild_lang + } + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +@router.post("/{guild_id}") +async def update_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update general settings for a specific guild.""" + from src.api.dashboard.routes import bot_instance + + if not bot_instance or not hasattr(bot_instance, 'settings_db'): + raise HTTPException(status_code=503, detail="Bot database not ready") + + data = await request.json() + + try: + # Update logic... + user_name = user.get("username", "Unbekannter User") + await send_dashboard_notification(guild_id, "Allgemein", user_name) + return {"success": True, "message": "Settings updated"} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save settings: {e}") + +# --- Welcome Module Routes --- + +@router.get("/{guild_id}/channels") +async def get_guild_channels(guild_id: int): + """Returns a list of text channels for the guild.""" + from src.api.dashboard.routes import bot_instance + if not bot_instance: + raise HTTPException(status_code=503, detail="Bot not ready") + + guild = bot_instance.get_guild(guild_id) + if not guild: + raise HTTPException(status_code=404, detail="Guild not found") + + channels = [ + {"id": str(c.id), "name": c.name} + for c in guild.text_channels + ] + return {"success": True, "channels": channels} + +@router.get("/{guild_id}/welcome") +async def get_welcome_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch welcome-specific settings.""" + db = WelcomeDatabase() + try: + settings = await db.get_welcome_settings(guild_id) + if settings and "channel_id" in settings and settings["channel_id"]: + settings["channel_id"] = str(settings["channel_id"]) + if settings and "auto_role_id" in settings and settings["auto_role_id"]: + settings["auto_role_id"] = str(settings["auto_role_id"]) + + return {"success": True, "data": settings or {}} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/welcome") +async def update_welcome_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update welcome-specific settings.""" + data = await request.json() + db = WelcomeDatabase() + + if "channel_id" in data and data["channel_id"]: + data["channel_id"] = int(data["channel_id"]) + if "auto_role_id" in data and data["auto_role_id"]: + data["auto_role_id"] = int(data["auto_role_id"]) + + try: + success = await db.update_welcome_settings(guild_id, **data) + if success: + user_name = user.get("username", "Unbekannter User") + # Invalidate cache if possible + from src.api.dashboard.routes import bot_instance + if bot_instance: + cog = bot_instance.get_cog("WelcomeSystem") + if cog and hasattr(cog, 'invalidate_cache'): + cog.invalidate_cache(guild_id) + + # Send notification to the welcome channel if configured + channel_id = data.get("channel_id") + await send_dashboard_notification(guild_id, "Welcome System", user_name, channel_id) + + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save welcome settings: {e}") + +# --- AntiSpam Module Routes --- + +@router.get("/{guild_id}/antispam") +async def get_antispam_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch AntiSpam-specific settings.""" + db = AntiSpamDatabase() + try: + settings = db.get_spam_settings(guild_id) + if settings and "log_channel_id" in settings and settings["log_channel_id"]: + settings["log_channel_id"] = str(settings["log_channel_id"]) + return {"success": True, "data": settings or {}} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/antispam") +async def update_antispam_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update AntiSpam-specific settings.""" + data = await request.json() + db = AntiSpamDatabase() + + if "log_channel_id" in data and data["log_channel_id"]: + data["log_channel_id"] = int(data["log_channel_id"]) + + try: + # Use set_spam_settings with direct kwargs if possible, or mapping + success = db.set_spam_settings( + guild_id, + max_messages=data.get("max_messages", 5), + time_frame=data.get("time_frame", 10), + log_channel_id=data.get("log_channel_id") + ) + if success: + user_name = user.get("username", "Unbekannter User") + from src.api.dashboard.routes import bot_instance + if bot_instance: + cog = bot_instance.get_cog("AntiSpam") + # Add cache invalidation if AntiSpam cog supports it + + await send_dashboard_notification(guild_id, "Anti-Spam", user_name, data.get("log_channel_id")) + + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save AntiSpam settings: {e}") + +# --- GlobalChat Module Routes --- + +@router.get("/{guild_id}/globalchat") +async def get_globalchat_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch GlobalChat-specific settings.""" + db = GlobalChatDatabase() + try: + settings = db.get_guild_settings(guild_id) + channel_id = db.get_globalchat_channel(guild_id) + settings["channel_id"] = str(channel_id) if channel_id else None + return {"success": True, "data": settings or {}} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/globalchat") +async def update_globalchat_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update GlobalChat-specific settings.""" + data = await request.json() + db = GlobalChatDatabase() + + try: + success = True + user_name = user.get("username", "Unbekannter User") + + # Handle channel_id separately + new_channel_id = data.get("channel_id") + if new_channel_id: + success = db.set_globalchat_channel(guild_id, int(new_channel_id)) + + # Update other settings + for key in ["filter_enabled", "nsfw_filter", "embed_color"]: + if key in data: + db.update_guild_setting(guild_id, key, data[key]) + + if success: + await send_dashboard_notification(guild_id, "Global Chat", user_name, int(new_channel_id) if new_channel_id else None) + + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save GlobalChat settings: {e}") + +# --- LevelSystem Module Routes --- + +@router.get("/{guild_id}/levels") +async def get_level_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch LevelSystem settings.""" + db = LevelDatabase() + try: + settings = db.get_guild_settings(guild_id) + return {"success": True, "data": settings or {}} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/levels") +async def update_level_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update LevelSystem settings.""" + data = await request.json() + db = LevelDatabase() + try: + success = db.update_guild_settings(guild_id, **data) + if success: + user_name = user.get("username", "Unbekannter User") + await send_dashboard_notification(guild_id, "Level-System", user_name) + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save level settings: {e}") + +# --- Logging Module Routes --- + +@router.get("/{guild_id}/logging") +async def get_logging_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch Logging settings.""" + db = LoggingDatabase() + try: + settings = db.get_guild_settings(guild_id) + if settings and "channel_id" in settings and settings["channel_id"]: + settings["channel_id"] = str(settings["channel_id"]) + return {"success": True, "data": settings or {}} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/logging") +async def update_logging_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update Logging settings.""" + data = await request.json() + db = LoggingDatabase() + + if "channel_id" in data and data["channel_id"]: + data["channel_id"] = int(data["channel_id"]) + + try: + success = db.update_guild_settings(guild_id, **data) + if success: + user_name = user.get("username", "Unbekannter User") + await send_dashboard_notification(guild_id, "Server-Log", user_name, data.get("channel_id")) + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save logging settings: {e}") + +# --- AutoRole Module Routes --- + +@router.get("/{guild_id}/autorole") +async def get_autorole_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch AutoRole settings.""" + db = AutoRoleDatabase() + try: + settings = db.get_guild_settings(guild_id) + if settings and "role_id" in settings and settings["role_id"]: + settings["role_id"] = str(settings["role_id"]) + return {"success": True, "data": settings or {}} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/autorole") +async def update_autorole_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update AutoRole settings.""" + data = await request.json() + db = AutoRoleDatabase() + + if "role_id" in data and data["role_id"]: + data["role_id"] = int(data["role_id"]) + + try: + success = db.update_guild_settings(guild_id, **data) + if success: + user_name = user.get("username", "Unbekannter User") + await send_dashboard_notification(guild_id, "Auto-Role", user_name) + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save autorole settings: {e}") + +# --- AutoDelete Module Routes --- + +@router.get("/{guild_id}/autodelete") +async def get_autodelete_settings(guild_id: int, user: dict = Depends(get_current_user)): + """Fetch AutoDelete settings.""" + db = AutoDeleteDB() + try: + settings = db.get_guild_settings(guild_id) + return {"success": True, "data": settings or []} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Database error: {e}") + +@router.post("/{guild_id}/autodelete") +async def update_autodelete_settings(guild_id: int, request: Request, user: dict = Depends(get_current_user)): + """Update AutoDelete settings.""" + data = await request.json() + db = AutoDeleteDB() + try: + # Assuming db.update_guild_settings(guild_id, data) where data is a list of channel configs + success = db.update_guild_settings(guild_id, data) + if success: + user_name = user.get("username", "Unbekannter User") + await send_dashboard_notification(guild_id, "Auto-Delete", user_name) + return {"success": success} + except Exception as e: + raise HTTPException(status_code=500, detail=f"Failed to save autodelete settings: {e}") diff --git a/src/bot/cogs/guild/globalchat.py b/src/bot/cogs/guild/globalchat.py index d520db9..5868a06 100644 --- a/src/bot/cogs/guild/globalchat.py +++ b/src/bot/cogs/guild/globalchat.py @@ -942,7 +942,7 @@ async def setup_globalchat( ) container.add_text(feature_text) - view = discord.ui.View(container, timeout=None) + view = discord.ui.DesignerView(container, timeout=None) await ctx.respond(view=view, ephemeral=True) except Exception as e: diff --git a/src/bot/cogs/guild/welcome.py b/src/bot/cogs/guild/welcome.py index 77d93c7..f8973c5 100644 --- a/src/bot/cogs/guild/welcome.py +++ b/src/bot/cogs/guild/welcome.py @@ -64,6 +64,7 @@ def __init__(self, bot): """ self.bot = bot self.db = WelcomeDatabase() + self.bot.welcome_db = self.db # Cache für bessere Performance self._settings_cache = {} self._cache_timeout = 300 # 5 Minuten Cache diff --git a/src/bot/cogs/management/autodelete.py b/src/bot/cogs/management/autodelete.py index 6c79776..711b529 100644 --- a/src/bot/cogs/management/autodelete.py +++ b/src/bot/cogs/management/autodelete.py @@ -21,7 +21,7 @@ def __init__(self, bot): @autodelete.command(name="setup", description="Richtet AutoDelete für einen Kanal ein.") async def setup(self, ctx, channel: Option(discord.TextChannel, "Kanal", required=True), - duration: Option(int, "Zeit in Sekunden (min: 60, max: 604800)", required=True), + duration: Option(int, "Zeit in Sekunden (min: 60s max: 7d (604800s))", required=True), exclude_pinned: Option(bool, "Angepinnte Nachrichten ausschließen", default=True), exclude_bots: Option(bool, "Bot-Nachrichten ausschließen", default=False)): diff --git a/src/bot/cogs/user/stats.py b/src/bot/cogs/user/stats.py index 40d7c63..58300a3 100644 --- a/src/bot/cogs/user/stats.py +++ b/src/bot/cogs/user/stats.py @@ -22,6 +22,7 @@ class EnhancedStatsCog(ezcord.Cog): def __init__(self, bot: commands.Bot): self.bot = bot self.db = StatsDB() + self.bot.stats_db = self.db self.level_db = LevelDatabase() self.cleanup_task.start() self.monthly_reset_task.start() diff --git a/src/bot/core/__init__.py b/src/bot/core/__init__.py index 3a4f213..61d58e5 100644 --- a/src/bot/core/__init__.py +++ b/src/bot/core/__init__.py @@ -11,7 +11,6 @@ from .database import DatabaseManager from .dashboard import DashboardTask from .utils import print_logo, format_uptime, truncate_text -from .constants import * __all__ = [ 'ConfigLoader', diff --git a/src/bot/core/constants.py b/src/scripts/constants.py similarity index 100% rename from src/bot/core/constants.py rename to src/scripts/constants.py diff --git a/src/web/App.tsx b/src/web/App.tsx index 869e4db..88118be 100644 --- a/src/web/App.tsx +++ b/src/web/App.tsx @@ -14,11 +14,14 @@ const Status = lazy(() => import("./pages/Status")); const CommandsPage = lazy(() => import("./pages/CommandsPage")); const TeamPage = lazy(() => import("./pages/TeamPage")); const RoadmapPage = lazy(() => import("./pages/RoadmapPage")); +const RoadmaPage = lazy(() => import("./pages/RoadmapPage")); const License = lazy(() => import("./pages/License").then(module => ({ default: module.License }))); +const LoginPage = lazy(() => import("./dashboard/LoginPage")); +const SettingsPage = lazy(() => import("./dashboard/SettingsPage")); +const AuthCallback = lazy(() => import("./pages/AuthCallback")); const queryClient = new QueryClient(); -// Loading fallback component const PageLoader = () => (

@@ -40,7 +43,38 @@ const PageLoader = () => (
); -const AppContent = () => { +const DashboardRoutes = () => { + const location = useLocation(); + + return ( + + + }> + + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + + ); +}; + +const MainRoutes = () => { const location = useLocation(); return ( @@ -70,6 +104,10 @@ const AppContent = () => { } /> } /> } /> + } /> + } /> + } /> + } /> } /> @@ -78,11 +116,28 @@ const AppContent = () => { ); }; +const AppContent = () => { + const hostname = window.location.hostname; + const isDashboard = hostname.startsWith("dashboard."); + + // Wenn wir auf der Dashboard Subdomain sind + if (isDashboard) { + return ; + } + + // Normale Webseite (Haupt-Domain) + return ; +}; + +import { AuthProvider } from "./components/AuthProvider"; + const App = () => ( - - - + + + + + ); diff --git a/src/web/components/AntiSpamSettings.tsx b/src/web/components/AntiSpamSettings.tsx new file mode 100644 index 0000000..d09914a --- /dev/null +++ b/src/web/components/AntiSpamSettings.tsx @@ -0,0 +1,186 @@ +import React, { useState, useEffect } from "react"; +import { motion } from "framer-motion"; +import { + Shield, + Hash, + Save, + Clock, + Zap, + AlertTriangle +} from "lucide-react"; +import { useAuth } from "../components/AuthProvider"; +import { toast } from "sonner"; +import { Button } from "./ui/button"; +import { Input } from "./ui/input"; +import { Label } from "./ui/label"; +import { Switch } from "./ui/switch"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card"; + +interface Channel { + id: string; + name: string; +} + +export default function AntiSpamSettings({ guildId }: { guildId: string }) { + const { token } = useAuth(); + const [isLoading, setIsLoading] = useState(false); + const [channels, setChannels] = useState([]); + + // AntiSpam Form States + const [maxMessages, setMaxMessages] = useState(5); + const [timeFrame, setTimeFrame] = useState(10); + const [logChannelId, setLogChannelId] = useState(""); + + useEffect(() => { + const fetchData = async () => { + if (!token || !guildId) return; + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + + // Fetch Channels + const channelRes = await fetch(`${baseUrl}/dashboard/settings/${guildId}/channels`, { + headers: { "Authorization": `Bearer ${token}` } + }); + if (channelRes.ok) { + const data = await channelRes.json(); + setChannels(data.channels || []); + } + + // Fetch AntiSpam Settings + const settingsRes = await fetch(`${baseUrl}/dashboard/settings/${guildId}/antispam`, { + headers: { "Authorization": `Bearer ${token}` } + }); + if (settingsRes.ok) { + const resData = await settingsRes.json(); + const s = resData.data; + if (s) { + setMaxMessages(s.max_messages ?? 5); + setTimeFrame(s.time_frame ?? 10); + setLogChannelId(s.log_channel_id || ""); + } + } + } catch (e) { + console.error("Fetch error", e); + } + }; + fetchData(); + }, [token, guildId]); + + const handleSave = async () => { + setIsLoading(true); + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const payload = { + max_messages: maxMessages, + time_frame: timeFrame, + log_channel_id: logChannelId + }; + + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/antispam`, { + method: "POST", + headers: { + "Authorization": `Bearer ${token}`, + "Content-Type": "application/json" + }, + body: JSON.stringify(payload) + }); + + if (res.ok) { + toast.success("AntiSpam-Einstellungen erfolgreich aktualisiert!"); + } else { + throw new Error("Save failed"); + } + } catch (e) { + toast.error("Fehler beim Speichern der AntiSpam-Einstellungen."); + } finally { + setIsLoading(false); + } + }; + + return ( +
+ + + + + Anti-Spam Schutz + + Verhindere Spam-Attacken auf deinem Server. + + + +
+
+ + setMaxMessages(parseInt(e.target.value))} + className="bg-black/20 border-white/10 h-12 rounded-xl" + min={1} + max={50} + /> +

Anzahl der Nachrichten, die in einem Zeitraum erlaubt sind.

+
+ +
+ + setTimeFrame(parseInt(e.target.value))} + className="bg-black/20 border-white/10 h-12 rounded-xl" + min={1} + max={60} + /> +

Der Zeitraum in dem die Nachrichten gezählt werden.

+
+
+ +
+ + +

Hier werden Spam-Vorfälle protokolliert.

+
+ +
+ +

+ Hinweis: Schärfere Einstellungen (weniger Nachrichten/längerer Zeitraum) können dazu führen, dass aktive User fälschlicherweise als Spammer erkannt werden. +

+
+
+
+ +
+ +
+
+ ); +} diff --git a/src/web/components/AuthProvider.tsx b/src/web/components/AuthProvider.tsx new file mode 100644 index 0000000..6e88219 --- /dev/null +++ b/src/web/components/AuthProvider.tsx @@ -0,0 +1,112 @@ +import React, { createContext, useContext, useState, useEffect, ReactNode } from "react"; + +interface User { + id: string; + username: string; + avatar: string | null; +} + +interface AuthContextType { + token: string | null; + user: any | null; + guilds: any[]; + selectedGuildId: string | null; + isAuthenticated: boolean; + login: (token: string, user: any, discordToken?: string) => void; + logout: () => void; + setSelectedGuildId: (id: string) => void; +} + +const AuthContext = createContext(undefined); + +export const AuthProvider = ({ children }: { children: ReactNode }) => { + const [token, setToken] = useState(localStorage.getItem("token")); + const [user, setUser] = useState(JSON.parse(localStorage.getItem("user") || "null")); + const [guilds, setGuilds] = useState([]); + const [selectedGuildId, setSelectedGuildId] = useState(localStorage.getItem("selectedGuildId")); + + const login = (newToken: string, newUser: any, newDiscordToken?: string) => { + setToken(newToken); + setUser(newUser); + localStorage.setItem("token", newToken); + localStorage.setItem("user", JSON.stringify(newUser)); + if (newDiscordToken) { + localStorage.setItem("discord_token", newDiscordToken); + } + }; + + const logout = () => { + setToken(null); + setUser(null); + setGuilds([]); + setSelectedGuildId(null); + localStorage.removeItem("token"); + localStorage.removeItem("user"); + localStorage.removeItem("discord_token"); + localStorage.removeItem("selectedGuildId"); + }; + + const handleSetSelectedGuildId = (id: string) => { + setSelectedGuildId(id); + localStorage.setItem("selectedGuildId", id); + }; + + // Fetch guilds and validate session if authenticated + useEffect(() => { + if (token) { + const discordToken = localStorage.getItem("discord_token"); + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + + fetch(`${baseUrl}/dashboard/auth/me`, { + headers: { + "Authorization": `Bearer ${token}`, + "X-Discord-Token": discordToken || "" + } + }) + .then(async (res) => { + if (res.status === 401) { + logout(); + throw new Error("Session expired"); + } + if (!res.ok) throw new Error("Failed to fetch user data"); + return res.json(); + }) + .then(data => { + if (data.user) setUser(data.user); + if (data.guilds) { + setGuilds(data.guilds); + // Select first guild if none selected + if (!selectedGuildId && data.guilds.length > 0) { + handleSetSelectedGuildId(data.guilds[0].id); + } + } + }) + .catch(err => { + console.error("Auth me error:", err); + }); + } + }, [token]); + + return ( + + {children} + + ); +}; + +export function useAuth() { + const context = useContext(AuthContext); + if (context === undefined) { + throw new Error("useAuth must be used within an AuthProvider"); + } + return context; +} diff --git a/src/web/components/AutoDeleteSettings.tsx b/src/web/components/AutoDeleteSettings.tsx new file mode 100644 index 0000000..29f61e9 --- /dev/null +++ b/src/web/components/AutoDeleteSettings.tsx @@ -0,0 +1,202 @@ +import React, { useState, useEffect } from "react"; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "./ui/card"; +import { Label } from "./ui/label"; +import { Switch } from "./ui/switch"; +import { Input } from "./ui/input"; +import { Button } from "./ui/button"; +import { + Trash2, + Save, + Clock, + Hash, + Plus, + X, + Search +} from "lucide-react"; +import { toast } from "sonner"; + +interface AutoDeleteSettingsProps { + guildId: string; + channels: any[]; +} + +interface ChannelConfig { + channel_id: string; + delay: number; +} + +export default function AutoDeleteSettings({ guildId, channels }: AutoDeleteSettingsProps) { + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [configs, setConfigs] = useState([]); + + useEffect(() => { + fetchSettings(); + }, [guildId]); + + const fetchSettings = async () => { + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/autodelete`, { + headers: { + "Authorization": `Bearer ${localStorage.getItem("token")}` + } + }); + const data = await res.json(); + if (data.success && data.data) { + setConfigs(data.data); + } + } catch (error) { + console.error("Failed to fetch autodelete settings:", error); + toast.error("Fehler beim Laden der Auto-Delete Einstellungen."); + } finally { + setLoading(false); + } + }; + + const handleSave = async () => { + setSaving(true); + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/autodelete`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${localStorage.getItem("token")}` + }, + body: JSON.stringify(configs) + }); + const data = await res.json(); + if (data.success) { + toast.success("Auto-Delete Einstellungen gespeichert! 🧹"); + } + } catch (error) { + console.error("Failed to save autodelete settings:", error); + toast.error("Fehler beim Speichern der Einstellungen."); + } finally { + setSaving(false); + } + }; + + const addChannel = () => { + setConfigs([...configs, { channel_id: "", delay: 60 }]); + }; + + const removeChannel = (index: number) => { + setConfigs(configs.filter((_, i) => i !== index)); + }; + + const updateChannel = (index: number, field: keyof ChannelConfig, value: string | number) => { + const newConfigs = [...configs]; + newConfigs[index] = { ...newConfigs[index], [field]: value }; + setConfigs(newConfigs); + }; + + if (loading) return ( +
+
+
+ ); + + return ( +
+ +
+ + +
+
+
+
+ +
+ Auto-Delete +
+ + Lösche Nachrichten in bestimmten Kanälen automatisch nach einer Zeit. + +
+ +
+
+ + + {configs.length === 0 ? ( +
+

Noch keine Kanäle konfiguriert.

+
+ ) : ( +
+ {configs.map((config, index) => ( +
+
+ + +
+
+ +
+ updateChannel(index, "delay", parseInt(e.target.value))} + className="bg-white/5 border-white/5 focus:border-primary/50 h-10 pl-10" + /> + +
+
+ +
+ ))} +
+ )} + +
+ +
+
+ +
+ ); +} diff --git a/src/web/components/AutoRoleSettings.tsx b/src/web/components/AutoRoleSettings.tsx new file mode 100644 index 0000000..3a041cc --- /dev/null +++ b/src/web/components/AutoRoleSettings.tsx @@ -0,0 +1,197 @@ +/// +import React, { useState, useEffect } from "react"; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "./ui/card"; +import { Label } from "./ui/label"; +import { Switch } from "./ui/switch"; +import { Input } from "./ui/input"; +import { Button } from "./ui/button"; +import { + UserPlus, + Save, + ShieldCheck, + AtSign, + UserCog, + Search +} from "lucide-react"; +import { toast } from "sonner"; + +interface AutoRoleSettingsProps { + guildId: string; + roles: any[]; +} + +export default function AutoRoleSettings({ guildId, roles }: AutoRoleSettingsProps) { + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [settings, setSettings] = useState({ + enabled: false, + role_id: "", + apply_on_join: true, + notify_user: false + }); + + useEffect(() => { + fetchSettings(); + }, [guildId]); + + const fetchSettings = async () => { + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/autorole`, { + headers: { + "Authorization": `Bearer ${localStorage.getItem("token")}` + } + }); + const data = await res.json(); + if (data.success && data.data) { + setSettings(prev => ({ ...prev, ...data.data })); + } + } catch (error) { + console.error("Failed to fetch autorole settings:", error); + toast.error("Fehler beim Laden der Auto-Rollen Einstellungen."); + } finally { + setLoading(false); + } + }; + + const handleSave = async () => { + setSaving(true); + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/autorole`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${localStorage.getItem("token")}` + }, + body: JSON.stringify(settings) + }); + const data = await res.json(); + if (data.success) { + toast.success("Auto-Rollen Einstellungen gespeichert! 🛡️"); + } + } catch (error) { + console.error("Failed to save autorole settings:", error); + toast.error("Fehler beim Speichern der Einstellungen."); + } finally { + setSaving(false); + } + }; + + if (loading) return ( +
+
+
+ ); + + return ( +
+ +
+ + +
+
+
+
+ +
+ Auto-Roles +
+ + Weist neuen Mitgliedern automatisch eine Rolle zu. + +
+
+ + setSettings({ ...settings, enabled: checked })} + className="data-[state=checked]:bg-primary" + /> +
+
+
+ + + {/* Role ID */} +
+ +
+ +
+ +
+
+
+

Stelle sicher, dass die Bot-Rolle über der Ziel-Rolle steht!

+
+ +
+
+
+ +
+

Bei Beitritt

+

Sofort beim Serverbeitritt zuweisen

+
+
+ setSettings({ ...settings, apply_on_join: checked })} + /> +
+ +
+
+ +
+

Nutzer benachrichtigen

+

Sende eine DM nach der Zuweisung

+
+
+ setSettings({ ...settings, notify_user: checked })} + /> +
+
+ +
+ +
+ + +
+ ); +} diff --git a/src/web/components/GlobalChatSettings.tsx b/src/web/components/GlobalChatSettings.tsx new file mode 100644 index 0000000..38bc0fe --- /dev/null +++ b/src/web/components/GlobalChatSettings.tsx @@ -0,0 +1,188 @@ +import React, { useState, useEffect } from "react"; +import { motion } from "framer-motion"; +import { + Globe, + Hash, + Save, + Shield, + Palette, + Eye +} from "lucide-react"; +import { useAuth } from "../components/AuthProvider"; +import { toast } from "sonner"; +import { Button } from "./ui/button"; +import { Input } from "./ui/input"; +import { Label } from "./ui/label"; +import { Switch } from "./ui/switch"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card"; + +interface Channel { + id: string; + name: string; +} + +export default function GlobalChatSettings({ guildId }: { guildId: string }) { + const { token } = useAuth(); + const [isLoading, setIsLoading] = useState(false); + const [channels, setChannels] = useState([]); + + // GlobalChat Form States + const [channelId, setChannelId] = useState(""); + const [filterEnabled, setFilterEnabled] = useState(true); + const [nsfwFilter, setNsfwFilter] = useState(true); + const [embedColor, setEmbedColor] = useState("#2463eb"); + + useEffect(() => { + const fetchData = async () => { + if (!token || !guildId) return; + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + + // Fetch Channels + const channelRes = await fetch(`${baseUrl}/dashboard/settings/${guildId}/channels`, { + headers: { "Authorization": `Bearer ${token}` } + }); + if (channelRes.ok) { + const data = await channelRes.json(); + setChannels(data.channels || []); + } + + // Fetch GlobalChat Settings + const settingsRes = await fetch(`${baseUrl}/dashboard/settings/${guildId}/globalchat`, { + headers: { "Authorization": `Bearer ${token}` } + }); + if (settingsRes.ok) { + const resData = await settingsRes.json(); + const s = resData.data; + if (s) { + setChannelId(s.channel_id || ""); + setFilterEnabled(s.filter_enabled ?? true); + setNsfwFilter(s.nsfw_filter ?? true); + setEmbedColor(s.embed_color || "#2463eb"); + } + } + } catch (e) { + console.error("Fetch error", e); + } + }; + fetchData(); + }, [token, guildId]); + + const handleSave = async () => { + setIsLoading(true); + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const payload = { + channel_id: channelId, + filter_enabled: filterEnabled, + nsfw_filter: nsfwFilter, + embed_color: embedColor + }; + + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/globalchat`, { + method: "POST", + headers: { + "Authorization": `Bearer ${token}`, + "Content-Type": "application/json" + }, + body: JSON.stringify(payload) + }); + + if (res.ok) { + toast.success("Global Chat erfolgreich aktualisiert!"); + } else { + throw new Error("Save failed"); + } + } catch (e) { + toast.error("Fehler beim Speichern der Global Chat Einstellungen."); + } finally { + setIsLoading(false); + } + }; + + return ( +
+ + + + + Global Chat System + + Verbinde deinen Server mit dem weltweiten ManagerX Netzwerk. + + + +
+ + +

Wähle den Kanal, der als Global Chat fungieren soll.

+
+ +
+
+
+ +

Blockiert automatisch Beleidigungen und Links.

+
+ +
+ +
+
+ +

Blockiert nicht jugendfreie Inhalte.

+
+ +
+
+ +
+ +
+ setEmbedColor(e.target.value)} + className="w-12 h-12 p-1 bg-transparent border-none cursor-pointer" + /> + setEmbedColor(e.target.value)} + className="bg-black/20 border-white/10 h-12 rounded-xl font-mono flex-1" + /> +
+

Die Farbe, in der deine Nachrichten global angezeigt werden.

+
+
+
+ +
+ +
+
+ ); +} diff --git a/src/web/components/GuildSelector.tsx b/src/web/components/GuildSelector.tsx new file mode 100644 index 0000000..78e178f --- /dev/null +++ b/src/web/components/GuildSelector.tsx @@ -0,0 +1,79 @@ +import React from "react"; +import { useAuth } from "./AuthProvider"; +import { ChevronDown, Server } from "lucide-react"; +import * as DropdownMenu from "@radix-ui/react-dropdown-menu"; + +export default function GuildSelector() { + const { guilds, selectedGuildId, setSelectedGuildId } = useAuth(); + + const selectedGuild = guilds.find(g => g.id === selectedGuildId); + + if (guilds.length === 0) return null; + + return ( + + + + + + + + + Deine Server + + + {guilds.map((guild) => ( + setSelectedGuildId(guild.id)} + > +
+ {guild.icon ? ( + + ) : ( +
+ {guild.name.charAt(0)} +
+ )} +
+ {guild.name} +
+ ))} + + {guilds.length === 0 && ( +
+

Keine Server mit Bot gefunden.

+
+ )} +
+
+
+ ); +} diff --git a/src/web/components/LevelSettings.tsx b/src/web/components/LevelSettings.tsx new file mode 100644 index 0000000..1d6d634 --- /dev/null +++ b/src/web/components/LevelSettings.tsx @@ -0,0 +1,245 @@ +/// +import React, { useState, useEffect } from "react"; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "./ui/card"; +import { Label } from "./ui/label"; +import { Switch } from "./ui/switch"; +import { Input } from "./ui/input"; +import { Button } from "./ui/button"; +import { + Trophy, + Save, + MessageSquare, + Hash, + Volume2, + Ban, + Sparkles, + BarChart3, + Search +} from "lucide-react"; +import { toast } from "sonner"; +import { cn } from "../lib/utils"; + +interface LevelSettingsProps { + guildId: string; + channels: any[]; +} + +export default function LevelSettings({ guildId, channels }: LevelSettingsProps) { + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [settings, setSettings] = useState({ + enabled: false, + xp_rate: 1.0, + level_up_message: "Glückwunsch {user}, du bist nun Level {level}!", + level_up_channel: "", + voice_xp: true, + announcement_enabled: true + }); + + useEffect(() => { + fetchSettings(); + }, [guildId]); + + const fetchSettings = async () => { + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/levels`, { + headers: { + "Authorization": `Bearer ${localStorage.getItem("token")}` + } + }); + const data = await res.json(); + if (data.success && data.data) { + setSettings(prev => ({ ...prev, ...data.data })); + } + } catch (error) { + console.error("Failed to fetch level settings:", error); + toast.error("Fehler beim Laden der Level-Einstellungen."); + } finally { + setLoading(false); + } + }; + + const handleSave = async () => { + setSaving(true); + try { + const baseUrl = import.meta.env.VITE_API_URL || 'http://localhost:8040'; + const res = await fetch(`${baseUrl}/dashboard/settings/${guildId}/levels`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Authorization": `Bearer ${localStorage.getItem("token")}` + }, + body: JSON.stringify(settings) + }); + const data = await res.json(); + if (data.success) { + toast.success("Level-System Einstellungen gespeichert! ✨"); + } else { + throw new Error(data.detail || "Unbekannter Fehler"); + } + } catch (error) { + console.error("Failed to save level settings:", error); + toast.error("Fehler beim Speichern der Einstellungen."); + } finally { + setSaving(false); + } + }; + + if (loading) return ( +
+
+
+ ); + + return ( +
+ +
+ + +
+
+
+
+ +
+ Level-System +
+ + Belohne aktive Mitglieder deiner Community mit XP und Leveln. + +
+
+ + setSettings({ ...settings, enabled: checked })} + className="data-[state=checked]:bg-primary" + /> +
+
+
+ + +
+ {/* XP Rate */} +
+ +
+ setSettings({ ...settings, xp_rate: parseFloat(e.target.value) })} + className="bg-white/5 border-white/10 focus:border-primary/50 transition-all rounded-xl h-12 pl-4" + /> +
+
+

Standard ist 1.0. Höhere Werte geben mehr XP.

+
+ + {/* Level Up Channel */} +
+ +
+ +
+ +
+
+
+
+
+ + {/* Level Up Message */} +
+ +
+