Code cleanup for 1.7.0

This commit is contained in:
LukeGus
2025-10-01 14:56:03 -05:00
parent 66c9937be9
commit 129e683f0c
19 changed files with 264 additions and 248 deletions

View File

@@ -79,4 +79,4 @@ body:
attributes: attributes:
label: Additional Context label: Additional Context
description: Any other context about the problem description: Any other context about the problem
placeholder: "Add any other context about the problem here..." placeholder: "Add any other context about the problem here..."

View File

@@ -33,4 +33,4 @@ body:
attributes: attributes:
label: Additional Context label: Additional Context
description: Any other context or screenshots about the feature request description: Any other context or screenshots about the feature request
placeholder: "Add any other context about the feature request here..." placeholder: "Add any other context about the feature request here..."

View File

@@ -45,7 +45,7 @@ If you would like, you can support the project here!\
Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a web-based Termix is an open-source, forever-free, self-hosted all-in-one server management platform. It provides a web-based
solution for managing your servers and infrastructure through a single, intuitive interface. Termix offers SSH terminal solution for managing your servers and infrastructure through a single, intuitive interface. Termix offers SSH terminal
access, SSH tunneling capabilities, and remote file management, with many more tools to come. access, SSH tunneling capabilities, remote file management, with many more tools to come.
# Features # Features
@@ -69,12 +69,13 @@ See [Projects](https://github.com/users/LukeGus/projects/3) for all planned feat
# Installation # Installation
Supported Devices: Supported Devices:
- Website (any modern browser like Google, Safari, and Firefox) - Website (any modern browser like Google, Safari, and Firefox)
- Windows (app) - Windows (app)
- Linux (app) - Linux (app)
- iOS (coming in a few days) - iOS (coming in a few days)
- Android (coming in a few days) - Android (coming in a few days)
- iPadOS and macOS coming soon - iPadOS and macOS are in progress
Visit the Termix [Docs](https://docs.termix.site/install) for more information on how to install Termix on all platforms. Otherwise, view Visit the Termix [Docs](https://docs.termix.site/install) for more information on how to install Termix on all platforms. Otherwise, view
a sample docker-compose file here: a sample docker-compose file here:

375
package-lock.json generated
View File

@@ -461,9 +461,9 @@
} }
}, },
"node_modules/@codemirror/legacy-modes": { "node_modules/@codemirror/legacy-modes": {
"version": "6.5.1", "version": "6.5.2",
"resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.1.tgz", "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.2.tgz",
"integrity": "sha512-DJYQQ00N1/KdESpZV7jg9hafof/iBNp9h7TYo1SLMk86TWl9uDsVdho2dzd81K+v4retmK6mdC7WpuOQDytQqw==", "integrity": "sha512-/jJbwSTazlQEDOQw2FJ8LEEKVS72pU0lx6oM54kGpL8t/NJ2Jda3CZ4pcltiKTdqYSRk3ug1B3pil1gsjA6+8Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/language": "^6.0.0" "@codemirror/language": "^6.0.0"
@@ -2632,24 +2632,24 @@
} }
}, },
"node_modules/@mux/mux-player": { "node_modules/@mux/mux-player": {
"version": "3.6.0", "version": "3.6.1",
"resolved": "https://registry.npmjs.org/@mux/mux-player/-/mux-player-3.6.0.tgz", "resolved": "https://registry.npmjs.org/@mux/mux-player/-/mux-player-3.6.1.tgz",
"integrity": "sha512-yVWmTMJUoKNZZxsINFmz7ZUUR3GC+Qf7b6Qv2GTmUoYn14pO1aXywHLlMLDohstLIvdeOdh6F/WsD2/gDVSOmQ==", "integrity": "sha512-QidL9CSkRBwa49ItphuDXWtarAiskP8AG/+vj5u0LsCa+VqObQxPfxE9t5S9YO/SDYHXqDMviMpmSzotSROGUQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@mux/mux-video": "0.27.0", "@mux/mux-video": "0.27.0",
"@mux/playback-core": "0.31.0", "@mux/playback-core": "0.31.0",
"media-chrome": "~4.13.1", "media-chrome": "~4.14.0",
"player.style": "^0.2.0" "player.style": "^0.2.0"
} }
}, },
"node_modules/@mux/mux-player-react": { "node_modules/@mux/mux-player-react": {
"version": "3.6.0", "version": "3.6.1",
"resolved": "https://registry.npmjs.org/@mux/mux-player-react/-/mux-player-react-3.6.0.tgz", "resolved": "https://registry.npmjs.org/@mux/mux-player-react/-/mux-player-react-3.6.1.tgz",
"integrity": "sha512-bh2Z1fQqNkKCNUMS/3VU6jL2iY22155ZSIyizfz+bVX0EYHqdsS/iG95iDYLPlzA8WPyIh+J210tme68e1qP+w==", "integrity": "sha512-YKIieu9GmFI73+1EcAvd63ftZ0Z9ilGbWo2dGXqQeyCEcagIN0oEcXWUPuIuxhvYB0XXsxB8RBAD8SigHkCYAQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@mux/mux-player": "3.6.0", "@mux/mux-player": "3.6.1",
"@mux/playback-core": "0.31.0", "@mux/playback-core": "0.31.0",
"prop-types": "^15.8.1" "prop-types": "^15.8.1"
}, },
@@ -4554,52 +4554,52 @@
} }
}, },
"node_modules/@tailwindcss/node": { "node_modules/@tailwindcss/node": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz",
"integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", "integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/remapping": "^2.3.4", "@jridgewell/remapping": "^2.3.4",
"enhanced-resolve": "^5.18.3", "enhanced-resolve": "^5.18.3",
"jiti": "^2.5.1", "jiti": "^2.6.0",
"lightningcss": "1.30.1", "lightningcss": "1.30.1",
"magic-string": "^0.30.18", "magic-string": "^0.30.19",
"source-map-js": "^1.2.1", "source-map-js": "^1.2.1",
"tailwindcss": "4.1.13" "tailwindcss": "4.1.14"
} }
}, },
"node_modules/@tailwindcss/oxide": { "node_modules/@tailwindcss/oxide": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz",
"integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==", "integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==",
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"detect-libc": "^2.0.4", "detect-libc": "^2.0.4",
"tar": "^7.4.3" "tar": "^7.5.1"
}, },
"engines": { "engines": {
"node": ">= 10" "node": ">= 10"
}, },
"optionalDependencies": { "optionalDependencies": {
"@tailwindcss/oxide-android-arm64": "4.1.13", "@tailwindcss/oxide-android-arm64": "4.1.14",
"@tailwindcss/oxide-darwin-arm64": "4.1.13", "@tailwindcss/oxide-darwin-arm64": "4.1.14",
"@tailwindcss/oxide-darwin-x64": "4.1.13", "@tailwindcss/oxide-darwin-x64": "4.1.14",
"@tailwindcss/oxide-freebsd-x64": "4.1.13", "@tailwindcss/oxide-freebsd-x64": "4.1.14",
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14",
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.14",
"@tailwindcss/oxide-linux-arm64-musl": "4.1.13", "@tailwindcss/oxide-linux-arm64-musl": "4.1.14",
"@tailwindcss/oxide-linux-x64-gnu": "4.1.13", "@tailwindcss/oxide-linux-x64-gnu": "4.1.14",
"@tailwindcss/oxide-linux-x64-musl": "4.1.13", "@tailwindcss/oxide-linux-x64-musl": "4.1.14",
"@tailwindcss/oxide-wasm32-wasi": "4.1.13", "@tailwindcss/oxide-wasm32-wasi": "4.1.14",
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.14",
"@tailwindcss/oxide-win32-x64-msvc": "4.1.13" "@tailwindcss/oxide-win32-x64-msvc": "4.1.14"
} }
}, },
"node_modules/@tailwindcss/oxide-android-arm64": { "node_modules/@tailwindcss/oxide-android-arm64": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz",
"integrity": "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==", "integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -4613,9 +4613,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-darwin-arm64": { "node_modules/@tailwindcss/oxide-darwin-arm64": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz",
"integrity": "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==", "integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -4629,9 +4629,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-darwin-x64": { "node_modules/@tailwindcss/oxide-darwin-x64": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz",
"integrity": "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==", "integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -4645,9 +4645,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-freebsd-x64": { "node_modules/@tailwindcss/oxide-freebsd-x64": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz",
"integrity": "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==", "integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -4661,9 +4661,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz",
"integrity": "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==", "integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -4677,9 +4677,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-arm64-gnu": { "node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz",
"integrity": "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==", "integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -4693,9 +4693,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-arm64-musl": { "node_modules/@tailwindcss/oxide-linux-arm64-musl": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz",
"integrity": "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==", "integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -4709,9 +4709,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-x64-gnu": { "node_modules/@tailwindcss/oxide-linux-x64-gnu": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz",
"integrity": "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==", "integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -4725,9 +4725,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-linux-x64-musl": { "node_modules/@tailwindcss/oxide-linux-x64-musl": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz",
"integrity": "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==", "integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -4741,9 +4741,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-wasm32-wasi": { "node_modules/@tailwindcss/oxide-wasm32-wasi": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz",
"integrity": "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==", "integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==",
"bundleDependencies": [ "bundleDependencies": [
"@napi-rs/wasm-runtime", "@napi-rs/wasm-runtime",
"@emnapi/core", "@emnapi/core",
@@ -4758,21 +4758,21 @@
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"@emnapi/core": "^1.4.5", "@emnapi/core": "^1.5.0",
"@emnapi/runtime": "^1.4.5", "@emnapi/runtime": "^1.5.0",
"@emnapi/wasi-threads": "^1.0.4", "@emnapi/wasi-threads": "^1.1.0",
"@napi-rs/wasm-runtime": "^0.2.12", "@napi-rs/wasm-runtime": "^1.0.5",
"@tybys/wasm-util": "^0.10.0", "@tybys/wasm-util": "^0.10.1",
"tslib": "^2.8.0" "tslib": "^2.4.0"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"
} }
}, },
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz",
"integrity": "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==", "integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -4786,9 +4786,9 @@
} }
}, },
"node_modules/@tailwindcss/oxide-win32-x64-msvc": { "node_modules/@tailwindcss/oxide-win32-x64-msvc": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz",
"integrity": "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==", "integrity": "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -4802,14 +4802,14 @@
} }
}, },
"node_modules/@tailwindcss/vite": { "node_modules/@tailwindcss/vite": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.13.tgz", "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.14.tgz",
"integrity": "sha512-0PmqLQ010N58SbMTJ7BVJ4I2xopiQn/5i6nlb4JmxzQf8zcS5+m2Cv6tqh+sfDwtIdjoEnOvwsGQ1hkUi8QEHQ==", "integrity": "sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tailwindcss/node": "4.1.13", "@tailwindcss/node": "4.1.14",
"@tailwindcss/oxide": "4.1.13", "@tailwindcss/oxide": "4.1.14",
"tailwindcss": "4.1.13" "tailwindcss": "4.1.14"
}, },
"peerDependencies": { "peerDependencies": {
"vite": "^5.2.0 || ^6 || ^7" "vite": "^5.2.0 || ^6 || ^7"
@@ -5041,12 +5041,12 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.5.2", "version": "24.6.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.6.1.tgz",
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==", "integrity": "sha512-ljvjjs3DNXummeIaooB4cLBKg2U6SPI6Hjra/9rRIy7CpM0HpLtG9HptkMKAb4HYWy5S7HUvJEuWgr/y0U8SHw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~7.12.0" "undici-types": "~7.13.0"
} }
}, },
"node_modules/@types/plist": { "node_modules/@types/plist": {
@@ -5083,9 +5083,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "19.1.15", "version": "19.1.17",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.15.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.17.tgz",
"integrity": "sha512-+kLxJpaJzXybyDyFXYADyP1cznTO8HSuBpenGlnKOAkH4hyNINiywvXS/tGJhsrGGP/gM185RA3xpjY0Yg4erA==", "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==",
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
"dependencies": { "dependencies": {
@@ -5093,9 +5093,9 @@
} }
}, },
"node_modules/@types/react-dom": { "node_modules/@types/react-dom": {
"version": "19.1.9", "version": "19.1.11",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.9.tgz", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.11.tgz",
"integrity": "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==", "integrity": "sha512-3BKc/yGdNTYQVVw4idqHtSOcFsgGuBbMveKCOgF8wQ5QtrYOc3jDIlzg3jef04zcXFIHLelyGlj0T+BJ8+KN+w==",
"devOptional": true, "devOptional": true,
"license": "MIT", "license": "MIT",
"peer": true, "peer": true,
@@ -5154,9 +5154,9 @@
} }
}, },
"node_modules/@types/ssh2/node_modules/@types/node": { "node_modules/@types/ssh2/node_modules/@types/node": {
"version": "18.19.127", "version": "18.19.129",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.127.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.129.tgz",
"integrity": "sha512-gSjxjrnKXML/yo0BO099uPixMqfpJU0TKYjpfLU7TrtA2WWDki412Np/RSTPRil1saKBhvVVKzVx/p/6p94nVA==", "integrity": "sha512-hrmi5jWt2w60ayox3iIXwpMEnfUvOLJCRtrOPbHtH15nTjvO7uhnelvrdAs0dO0/zl5DZ3ZbahiaXEVb54ca/A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -5212,17 +5212,17 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz",
"integrity": "sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw==", "integrity": "sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.44.1", "@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/type-utils": "8.44.1", "@typescript-eslint/type-utils": "8.45.0",
"@typescript-eslint/utils": "8.44.1", "@typescript-eslint/utils": "8.45.0",
"@typescript-eslint/visitor-keys": "8.44.1", "@typescript-eslint/visitor-keys": "8.45.0",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^7.0.0", "ignore": "^7.0.0",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
@@ -5236,7 +5236,7 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.44.1", "@typescript-eslint/parser": "^8.45.0",
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0" "typescript": ">=4.8.4 <6.0.0"
} }
@@ -5252,17 +5252,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.45.0.tgz",
"integrity": "sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw==", "integrity": "sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.44.1", "@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.44.1", "@typescript-eslint/typescript-estree": "8.45.0",
"@typescript-eslint/visitor-keys": "8.44.1", "@typescript-eslint/visitor-keys": "8.45.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -5303,14 +5302,14 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/project-service": { "node_modules/@typescript-eslint/project-service": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.45.0.tgz",
"integrity": "sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA==", "integrity": "sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.44.1", "@typescript-eslint/tsconfig-utils": "^8.45.0",
"@typescript-eslint/types": "^8.44.1", "@typescript-eslint/types": "^8.45.0",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -5350,14 +5349,14 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz",
"integrity": "sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg==", "integrity": "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.44.1" "@typescript-eslint/visitor-keys": "8.45.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5368,9 +5367,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.45.0.tgz",
"integrity": "sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ==", "integrity": "sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -5385,15 +5384,15 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.45.0.tgz",
"integrity": "sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g==", "integrity": "sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.44.1", "@typescript-eslint/typescript-estree": "8.45.0",
"@typescript-eslint/utils": "8.44.1", "@typescript-eslint/utils": "8.45.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.1.0"
}, },
@@ -5435,9 +5434,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz",
"integrity": "sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ==", "integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -5449,16 +5448,16 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz",
"integrity": "sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A==", "integrity": "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.44.1", "@typescript-eslint/project-service": "8.45.0",
"@typescript-eslint/tsconfig-utils": "8.44.1", "@typescript-eslint/tsconfig-utils": "8.45.0",
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.45.0",
"@typescript-eslint/visitor-keys": "8.44.1", "@typescript-eslint/visitor-keys": "8.45.0",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
@@ -5542,16 +5541,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.45.0.tgz",
"integrity": "sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg==", "integrity": "sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.7.0", "@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.44.1", "@typescript-eslint/scope-manager": "8.45.0",
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.45.0",
"@typescript-eslint/typescript-estree": "8.44.1" "@typescript-eslint/typescript-estree": "8.45.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -5566,13 +5565,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz",
"integrity": "sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw==", "integrity": "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.44.1", "@typescript-eslint/types": "8.45.0",
"eslint-visitor-keys": "^4.2.1" "eslint-visitor-keys": "^4.2.1"
}, },
"engines": { "engines": {
@@ -7643,7 +7642,6 @@
"integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"app-builder-lib": "26.0.12", "app-builder-lib": "26.0.12",
"builder-util": "26.0.11", "builder-util": "26.0.11",
@@ -7735,9 +7733,9 @@
} }
}, },
"node_modules/dotenv": { "node_modules/dotenv": {
"version": "17.2.2", "version": "17.2.3",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
"integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
@@ -8165,9 +8163,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron/node_modules/@types/node": { "node_modules/electron/node_modules/@types/node": {
"version": "22.18.6", "version": "22.18.8",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz",
"integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==", "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -9943,9 +9941,9 @@
} }
}, },
"node_modules/i18next": { "node_modules/i18next": {
"version": "25.5.2", "version": "25.5.3",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.5.2.tgz", "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.5.3.tgz",
"integrity": "sha512-lW8Zeh37i/o0zVr+NoCHfNnfvVw+M6FQbRp36ZZ/NyHDJ3NJVpp2HhAUyU9WafL5AssymNoOjMRB48mmx2P6Hw==", "integrity": "sha512-joFqorDeQ6YpIXni944upwnuHBf5IoPMuqAchGVeQLdWC2JOjxgM9V8UGLhNIIH/Q8QleRxIi0BSRQehSrDLcg==",
"funding": [ "funding": [
{ {
"type": "individual", "type": "individual",
@@ -10365,9 +10363,9 @@
} }
}, },
"node_modules/jiti": { "node_modules/jiti": {
"version": "2.6.0", "version": "2.6.1",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.0.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
"integrity": "sha512-VXe6RjJkBPj0ohtqaO8vSWP3ZhAKo66fKrFNCll4BTcwljPLz03pCbaNKfzGP5MbrCYcbJ7v0nOYYwUzTEIdXQ==", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"jiti": "lib/jiti-cli.mjs" "jiti": "lib/jiti-cli.mjs"
@@ -11450,9 +11448,9 @@
} }
}, },
"node_modules/media-chrome": { "node_modules/media-chrome": {
"version": "4.13.1", "version": "4.14.0",
"resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.13.1.tgz", "resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.14.0.tgz",
"integrity": "sha512-jPPwYrFkM4ky27/xNYEeyRPOBC7qvru4Oydy7vQHMHplXLQJmjtcauhlLPvG0O5kkYFEaOBXv5zGYes/UxOoVw==", "integrity": "sha512-IEdFb4blyF15vLvQzLIn6USJBv7Kf2ne+TfLQKBYI5Z0f9VEBVZz5MKy4Uhi0iA9lStl2S9ENIujJRuJIa5OiA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ce-la-react": "^0.3.0" "ce-la-react": "^0.3.0"
@@ -12930,6 +12928,15 @@
"media-chrome": "~4.13.0" "media-chrome": "~4.13.0"
} }
}, },
"node_modules/player.style/node_modules/media-chrome": {
"version": "4.13.1",
"resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.13.1.tgz",
"integrity": "sha512-jPPwYrFkM4ky27/xNYEeyRPOBC7qvru4Oydy7vQHMHplXLQJmjtcauhlLPvG0O5kkYFEaOBXv5zGYes/UxOoVw==",
"license": "MIT",
"dependencies": {
"ce-la-react": "^0.3.0"
}
},
"node_modules/plist": { "node_modules/plist": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
@@ -13670,9 +13677,9 @@
} }
}, },
"node_modules/react-simple-keyboard": { "node_modules/react-simple-keyboard": {
"version": "3.8.123", "version": "3.8.125",
"resolved": "https://registry.npmjs.org/react-simple-keyboard/-/react-simple-keyboard-3.8.123.tgz", "resolved": "https://registry.npmjs.org/react-simple-keyboard/-/react-simple-keyboard-3.8.125.tgz",
"integrity": "sha512-aSJiQYzqX+G1hciKjH0jhuf564HO7fMZljrXYPeie3Un1va34whnSQmCYVj64nvOE5bgrHipJgFCiuHLGQiRHw==", "integrity": "sha512-8+PbmGA2auM7V57hapHsKV7IJcJVl0QNNW09RJQ7xCiohHuZNKvqrxGvisxhhr7X8C8TKulxbqdxjZbFelwO7w==",
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
"react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
@@ -14986,9 +14993,9 @@
} }
}, },
"node_modules/tailwindcss": { "node_modules/tailwindcss": {
"version": "4.1.13", "version": "4.1.14",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz",
"integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", "integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/tapable": { "node_modules/tapable": {
@@ -15468,9 +15475,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.9.2", "version": "5.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true, "peer": true,
@@ -15483,16 +15490,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.44.1", "version": "8.45.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.44.1.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.45.0.tgz",
"integrity": "sha512-0ws8uWGrUVTjEeN2OM4K1pLKHK/4NiNP/vz6ns+LjT/6sqpaYzIVFajZb1fj/IDwpsrrHb3Jy0Qm5u9CPcKaeg==", "integrity": "sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.44.1", "@typescript-eslint/eslint-plugin": "8.45.0",
"@typescript-eslint/parser": "8.44.1", "@typescript-eslint/parser": "8.45.0",
"@typescript-eslint/typescript-estree": "8.44.1", "@typescript-eslint/typescript-estree": "8.45.0",
"@typescript-eslint/utils": "8.44.1" "@typescript-eslint/utils": "8.45.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -15533,9 +15540,9 @@
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "7.12.0", "version": "7.13.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz",
"integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", "integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/unified": { "node_modules/unified": {

View File

@@ -496,7 +496,7 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
process.env.NODE_ENV === "production" process.env.NODE_ENV === "production"
? path.join(process.env.DATA_DIR || "./db/data", ".temp", "exports") ? path.join(process.env.DATA_DIR || "./db/data", ".temp", "exports")
: path.join(os.tmpdir(), "termix-exports"); : path.join(os.tmpdir(), "termix-exports");
try { try {
if (!fs.existsSync(tempDir)) { if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir, { recursive: true }); fs.mkdirSync(tempDir, { recursive: true });
@@ -861,7 +861,7 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
res.setHeader("Content-Disposition", `attachment; filename="${filename}"`); res.setHeader("Content-Disposition", `attachment; filename="${filename}"`);
const fileStream = fs.createReadStream(tempPath); const fileStream = fs.createReadStream(tempPath);
fileStream.on("error", (streamError) => { fileStream.on("error", (streamError) => {
apiLogger.error("File stream error during export", streamError, { apiLogger.error("File stream error during export", streamError, {
operation: "export_file_stream_error", operation: "export_file_stream_error",
@@ -882,13 +882,13 @@ app.post("/database/export", authenticateJWT, async (req, res) => {
userId, userId,
filename, filename,
}); });
fs.unlink(tempPath, (err) => { fs.unlink(tempPath, (err) => {
if (err) { if (err) {
apiLogger.warn("Failed to clean up export file", { apiLogger.warn("Failed to clean up export file", {
operation: "export_cleanup_failed", operation: "export_cleanup_failed",
path: tempPath, path: tempPath,
error: err.message error: err.message,
}); });
} }
}); });

View File

@@ -569,7 +569,9 @@ async function connectSSHTunnel(
if (tunnelConfig.endpointCredentialId && tunnelConfig.endpointUserId) { if (tunnelConfig.endpointCredentialId && tunnelConfig.endpointUserId) {
try { try {
const userDataKey = DataCrypto.getUserDataKey(tunnelConfig.endpointUserId); const userDataKey = DataCrypto.getUserDataKey(
tunnelConfig.endpointUserId,
);
if (userDataKey) { if (userDataKey) {
const credentials = await SimpleDBOps.select( const credentials = await SimpleDBOps.select(
getDb() getDb()

View File

@@ -56,10 +56,11 @@ export class DatabaseMigration {
if (hasEncryptedDb && hasUnencryptedDb) { if (hasEncryptedDb && hasUnencryptedDb) {
const unencryptedSize = fs.statSync(this.unencryptedDbPath).size; const unencryptedSize = fs.statSync(this.unencryptedDbPath).size;
const encryptedSize = fs.statSync(this.encryptedDbPath).size; const encryptedSize = fs.statSync(this.encryptedDbPath).size;
if (unencryptedSize === 0) { if (unencryptedSize === 0) {
needsMigration = false; needsMigration = false;
reason = "Empty unencrypted database found alongside encrypted database. Removing empty file."; reason =
"Empty unencrypted database found alongside encrypted database. Removing empty file.";
try { try {
fs.unlinkSync(this.unencryptedDbPath); fs.unlinkSync(this.unencryptedDbPath);
databaseLogger.info("Removed empty unencrypted database file", { databaseLogger.info("Removed empty unencrypted database file", {

View File

@@ -28,7 +28,7 @@ class SystemCrypto {
const dataDir = process.env.DATA_DIR || "./db/data"; const dataDir = process.env.DATA_DIR || "./db/data";
const envPath = path.join(dataDir, ".env"); const envPath = path.join(dataDir, ".env");
try { try {
const envContent = await fs.readFile(envPath, "utf8"); const envContent = await fs.readFile(envPath, "utf8");
const jwtMatch = envContent.match(/^JWT_SECRET=(.+)$/m); const jwtMatch = envContent.match(/^JWT_SECRET=(.+)$/m);
@@ -37,8 +37,7 @@ class SystemCrypto {
process.env.JWT_SECRET = jwtMatch[1]; process.env.JWT_SECRET = jwtMatch[1];
return; return;
} }
} catch { } catch {}
}
await this.generateAndGuideUser(); await this.generateAndGuideUser();
} catch (error) { } catch (error) {
@@ -66,7 +65,7 @@ class SystemCrypto {
const dataDir = process.env.DATA_DIR || "./db/data"; const dataDir = process.env.DATA_DIR || "./db/data";
const envPath = path.join(dataDir, ".env"); const envPath = path.join(dataDir, ".env");
try { try {
const envContent = await fs.readFile(envPath, "utf8"); const envContent = await fs.readFile(envPath, "utf8");
const dbKeyMatch = envContent.match(/^DATABASE_KEY=(.+)$/m); const dbKeyMatch = envContent.match(/^DATABASE_KEY=(.+)$/m);
@@ -75,8 +74,7 @@ class SystemCrypto {
process.env.DATABASE_KEY = dbKeyMatch[1]; process.env.DATABASE_KEY = dbKeyMatch[1];
return; return;
} }
} catch { } catch {}
}
await this.generateAndGuideDatabaseKey(); await this.generateAndGuideDatabaseKey();
} catch (error) { } catch (error) {
@@ -104,7 +102,7 @@ class SystemCrypto {
const dataDir = process.env.DATA_DIR || "./db/data"; const dataDir = process.env.DATA_DIR || "./db/data";
const envPath = path.join(dataDir, ".env"); const envPath = path.join(dataDir, ".env");
try { try {
const envContent = await fs.readFile(envPath, "utf8"); const envContent = await fs.readFile(envPath, "utf8");
const tokenMatch = envContent.match(/^INTERNAL_AUTH_TOKEN=(.+)$/m); const tokenMatch = envContent.match(/^INTERNAL_AUTH_TOKEN=(.+)$/m);
@@ -113,8 +111,7 @@ class SystemCrypto {
process.env.INTERNAL_AUTH_TOKEN = tokenMatch[1]; process.env.INTERNAL_AUTH_TOKEN = tokenMatch[1];
return; return;
} }
} catch { } catch {}
}
await this.generateAndGuideInternalAuthToken(); await this.generateAndGuideInternalAuthToken();
} catch (error) { } catch (error) {

View File

@@ -71,7 +71,7 @@ class UserCrypto {
async setupOIDCUserEncryption(userId: string): Promise<void> { async setupOIDCUserEncryption(userId: string): Promise<void> {
const DEK = crypto.randomBytes(UserCrypto.DEK_LENGTH); const DEK = crypto.randomBytes(UserCrypto.DEK_LENGTH);
const now = Date.now(); const now = Date.now();
this.userSessions.set(userId, { this.userSessions.set(userId, {
dataKey: Buffer.from(DEK), dataKey: Buffer.from(DEK),
@@ -319,7 +319,8 @@ class UserCrypto {
} }
private deriveOIDCSystemKey(userId: string): Buffer { private deriveOIDCSystemKey(userId: string): Buffer {
const systemSecret = process.env.OIDC_SYSTEM_SECRET || "termix-oidc-system-secret-default"; const systemSecret =
process.env.OIDC_SYSTEM_SECRET || "termix-oidc-system-secret-default";
const salt = Buffer.from(userId, "utf8"); const salt = Buffer.from(userId, "utf8");
return crypto.pbkdf2Sync( return crypto.pbkdf2Sync(
systemSecret, systemSecret,

View File

@@ -271,7 +271,8 @@ export function AdminSettings({
setExportLoading(true); setExportLoading(true);
try { try {
const isDev = process.env.NODE_ENV === "development" && const isDev =
process.env.NODE_ENV === "development" &&
(window.location.port === "3000" || (window.location.port === "3000" ||
window.location.port === "5173" || window.location.port === "5173" ||
window.location.port === "" || window.location.port === "" ||
@@ -340,7 +341,8 @@ export function AdminSettings({
setImportLoading(true); setImportLoading(true);
try { try {
const isDev = process.env.NODE_ENV === "development" && const isDev =
process.env.NODE_ENV === "development" &&
(window.location.port === "3000" || (window.location.port === "3000" ||
window.location.port === "5173" || window.location.port === "5173" ||
window.location.port === "" || window.location.port === "" ||

View File

@@ -87,7 +87,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
initialHost || null, initialHost || null,
); );
const [currentPath, setCurrentPath] = useState( const [currentPath, setCurrentPath] = useState(
initialHost?.defaultPath || "/" initialHost?.defaultPath || "/",
); );
const [files, setFiles] = useState<FileItem[]>([]); const [files, setFiles] = useState<FileItem[]>([]);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -184,7 +184,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
const handleCloseWithError = useCallback( const handleCloseWithError = useCallback(
(errorMessage: string) => { (errorMessage: string) => {
if (isClosing) return; // Prevent duplicate calls if (isClosing) return;
setIsClosing(true); setIsClosing(true);
toast.error(errorMessage); toast.error(errorMessage);
if (onClose) { if (onClose) {
@@ -758,10 +758,10 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) {
const windowCount = Date.now() % 10; const windowCount = Date.now() % 10;
const baseOffsetX = 120 + windowCount * 30; const baseOffsetX = 120 + windowCount * 30;
const baseOffsetY = 120 + windowCount * 30; const baseOffsetY = 120 + windowCount * 30;
const maxOffsetX = Math.max(0, window.innerWidth - 800 - 100); const maxOffsetX = Math.max(0, window.innerWidth - 800 - 100);
const maxOffsetY = Math.max(0, window.innerHeight - 600 - 100); const maxOffsetY = Math.max(0, window.innerHeight - 600 - 100);
const offsetX = Math.min(baseOffsetX, maxOffsetX); const offsetX = Math.min(baseOffsetX, maxOffsetX);
const offsetY = Math.min(baseOffsetY, maxOffsetY); const offsetY = Math.min(baseOffsetY, maxOffsetY);

View File

@@ -355,11 +355,22 @@ export function FileViewer({
setShowLargeFileWarning(false); setShowLargeFileWarning(false);
} }
if (fileTypeInfo.type === "image" && file.name.toLowerCase().endsWith('.svg') && content) { if (
fileTypeInfo.type === "image" &&
file.name.toLowerCase().endsWith(".svg") &&
content
) {
setImageLoading(false); setImageLoading(false);
setImageLoadError(false); setImageLoadError(false);
} }
}, [content, savedContent, fileTypeInfo.type, isLargeFile, forceShowAsText, file.name]); }, [
content,
savedContent,
fileTypeInfo.type,
isLargeFile,
forceShowAsText,
file.name,
]);
const handleContentChange = (newContent: string) => { const handleContentChange = (newContent: string) => {
setEditedContent(newContent); setEditedContent(newContent);
@@ -706,8 +717,8 @@ export function FileViewer({
</Button> </Button>
)} )}
</div> </div>
) : file.name.toLowerCase().endsWith('.svg') ? ( ) : file.name.toLowerCase().endsWith(".svg") ? (
<div <div
className="max-w-full max-h-full flex items-center justify-center" className="max-w-full max-h-full flex items-center justify-center"
style={{ maxHeight: "calc(100vh - 200px)" }} style={{ maxHeight: "calc(100vh - 200px)" }}
dangerouslySetInnerHTML={{ __html: content }} dangerouslySetInnerHTML={{ __html: content }}

View File

@@ -9,15 +9,15 @@ interface DragAndDropState {
interface UseDragAndDropProps { interface UseDragAndDropProps {
onFilesDropped: (files: FileList) => void; onFilesDropped: (files: FileList) => void;
onError?: (error: string) => void; onError?: (error: string) => void;
maxFileSize?: number; // in MB maxFileSize?: number;
allowedTypes?: string[]; allowedTypes?: string[];
} }
export function useDragAndDrop({ export function useDragAndDrop({
onFilesDropped, onFilesDropped,
onError, onError,
maxFileSize = 5120, // 5GB default - much more reasonable maxFileSize = 5120,
allowedTypes = [], // empty means all types allowed allowedTypes = [],
}: UseDragAndDropProps) { }: UseDragAndDropProps) {
const [state, setState] = useState<DragAndDropState>({ const [state, setState] = useState<DragAndDropState>({
isDragging: false, isDragging: false,
@@ -32,28 +32,23 @@ export function useDragAndDrop({
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
const file = files[i]; const file = files[i];
// Check file size
if (file.size > maxSizeBytes) { if (file.size > maxSizeBytes) {
return `File "${file.name}" is too large. Maximum size is ${maxFileSize}MB.`; return `File "${file.name}" is too large. Maximum size is ${maxFileSize}MB.`;
} }
// Check file type if restrictions exist
if (allowedTypes.length > 0) { if (allowedTypes.length > 0) {
const fileExt = file.name.split(".").pop()?.toLowerCase(); const fileExt = file.name.split(".").pop()?.toLowerCase();
const mimeType = file.type.toLowerCase(); const mimeType = file.type.toLowerCase();
const isAllowed = allowedTypes.some((type) => { const isAllowed = allowedTypes.some((type) => {
// Check by extension
if (type.startsWith(".")) { if (type.startsWith(".")) {
return fileExt === type.slice(1); return fileExt === type.slice(1);
} }
// Check by MIME type
if (type.includes("/")) { if (type.includes("/")) {
return ( return (
mimeType === type || mimeType.startsWith(type.replace("*", "")) mimeType === type || mimeType.startsWith(type.replace("*", ""))
); );
} }
// Check by category
switch (type) { switch (type) {
case "image": case "image":
return mimeType.startsWith("image/"); return mimeType.startsWith("image/");
@@ -114,7 +109,6 @@ export function useDragAndDrop({
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// Set dropEffect to indicate what operation is allowed
e.dataTransfer.dropEffect = "copy"; e.dataTransfer.dropEffect = "copy";
}, []); }, []);

View File

@@ -214,7 +214,11 @@ export const Terminal = forwardRef<any, SSHTerminalProps>(function SSHTerminal(
); );
reconnectTimeoutRef.current = setTimeout(() => { reconnectTimeoutRef.current = setTimeout(() => {
if (isUnmountingRef.current || shouldNotReconnectRef.current || wasDisconnectedBySSH.current) { if (
isUnmountingRef.current ||
shouldNotReconnectRef.current ||
wasDisconnectedBySSH.current
) {
isReconnectingRef.current = false; isReconnectingRef.current = false;
return; return;
} }

View File

@@ -143,7 +143,7 @@ function AppContent() {
isAdmin={isAdmin} isAdmin={isAdmin}
username={username} username={username}
> >
<div <div
className="h-screen w-full visible pointer-events-auto static overflow-hidden" className="h-screen w-full visible pointer-events-auto static overflow-hidden"
style={{ display: showTerminalView ? "block" : "none" }} style={{ display: showTerminalView ? "block" : "none" }}
> >

View File

@@ -82,7 +82,6 @@ export function HomepageAuth({
const [registrationAllowed, setRegistrationAllowed] = useState(true); const [registrationAllowed, setRegistrationAllowed] = useState(true);
const [oidcConfigured, setOidcConfigured] = useState(false); const [oidcConfigured, setOidcConfigured] = useState(false);
// Legacy reset states (kept for compatibility)
const [resetStep, setResetStep] = useState< const [resetStep, setResetStep] = useState<
"initiate" | "verify" | "newPassword" "initiate" | "verify" | "newPassword"
>("initiate"); >("initiate");
@@ -106,8 +105,7 @@ export function HomepageAuth({
const clearJWTOnLoad = async () => { const clearJWTOnLoad = async () => {
try { try {
await logoutUser(); await logoutUser();
} catch (error) { } catch (error) {}
}
}; };
clearJWTOnLoad(); clearJWTOnLoad();
@@ -242,7 +240,6 @@ export function HomepageAuth({
setIsAdmin(false); setIsAdmin(false);
setUsername(null); setUsername(null);
setUserId(null); setUserId(null);
// HttpOnly cookies cannot be cleared from JavaScript - backend handles this
if (err?.response?.data?.error?.includes("Database")) { if (err?.response?.data?.error?.includes("Database")) {
setDbConnectionFailed(true); setDbConnectionFailed(true);
} else { } else {
@@ -253,8 +250,6 @@ export function HomepageAuth({
} }
} }
// ===== Legacy password reset functions (deprecated) =====
async function handleInitiatePasswordReset() { async function handleInitiatePasswordReset() {
setError(null); setError(null);
setResetLoading(true); setResetLoading(true);
@@ -317,7 +312,6 @@ export function HomepageAuth({
setResetSuccess(true); setResetSuccess(true);
toast.success(t("messages.passwordResetSuccess")); toast.success(t("messages.passwordResetSuccess"));
// Immediately redirect to login after successful reset
setTab("login"); setTab("login");
resetPasswordState(); resetPasswordState();
} catch (err: any) { } catch (err: any) {
@@ -372,7 +366,7 @@ export function HomepageAuth({
setUsername(res.username || null); setUsername(res.username || null);
setUserId(res.userId || null); setUserId(res.userId || null);
setDbError(null); setDbError(null);
setTimeout(() => { setTimeout(() => {
onAuthSuccess({ onAuthSuccess({
isAdmin: !!res.is_admin, isAdmin: !!res.is_admin,
@@ -380,7 +374,7 @@ export function HomepageAuth({
userId: res.userId || null, userId: res.userId || null,
}); });
}, 100); }, 100);
setInternalLoggedIn(true); setInternalLoggedIn(true);
setTotpRequired(false); setTotpRequired(false);
setTotpCode(""); setTotpCode("");
@@ -392,7 +386,7 @@ export function HomepageAuth({
err?.response?.data?.error || err?.response?.data?.error ||
err?.message || err?.message ||
t("errors.invalidTotpCode"); t("errors.invalidTotpCode");
if (errorCode === "SESSION_EXPIRED") { if (errorCode === "SESSION_EXPIRED") {
setTotpRequired(false); setTotpRequired(false);
setTotpCode(""); setTotpCode("");

View File

@@ -352,7 +352,7 @@ export function HomepageAuth({
setUsername(res.username || null); setUsername(res.username || null);
setUserId(res.userId || null); setUserId(res.userId || null);
setDbError(null); setDbError(null);
setTimeout(() => { setTimeout(() => {
onAuthSuccess({ onAuthSuccess({
isAdmin: !!res.is_admin, isAdmin: !!res.is_admin,
@@ -360,7 +360,7 @@ export function HomepageAuth({
userId: res.userId || null, userId: res.userId || null,
}); });
}, 100); }, 100);
setInternalLoggedIn(true); setInternalLoggedIn(true);
setTotpRequired(false); setTotpRequired(false);
setTotpCode(""); setTotpCode("");
@@ -372,7 +372,7 @@ export function HomepageAuth({
err?.response?.data?.error || err?.response?.data?.error ||
err?.message || err?.message ||
t("errors.invalidTotpCode"); t("errors.invalidTotpCode");
if (errorCode === "SESSION_EXPIRED") { if (errorCode === "SESSION_EXPIRED") {
setTotpRequired(false); setTotpRequired(false);
setTotpCode(""); setTotpCode("");
@@ -566,7 +566,9 @@ export function HomepageAuth({
type="button" type="button"
variant="outline" variant="outline"
className="w-full h-11 text-base font-semibold" className="w-full h-11 text-base font-semibold"
onClick={() => window.open("https://docs.termix.site/install", "_blank")} onClick={() =>
window.open("https://docs.termix.site/install", "_blank")
}
> >
{t("mobile.viewMobileAppDocs")} {t("mobile.viewMobileAppDocs")}
</Button> </Button>
@@ -900,7 +902,9 @@ export function HomepageAuth({
type="button" type="button"
variant="outline" variant="outline"
className="w-full h-11 text-base font-semibold" className="w-full h-11 text-base font-semibold"
onClick={() => window.open("https://docs.termix.site/install", "_blank")} onClick={() =>
window.open("https://docs.termix.site/install", "_blank")
}
> >
{t("mobile.viewMobileAppDocs")} {t("mobile.viewMobileAppDocs")}
</Button> </Button>

View File

@@ -164,7 +164,9 @@ const AppContent: FC = () => {
</p> </p>
<button <button
className="mt-4 px-6 py-3 bg-primary text-primary-foreground rounded-lg font-semibold hover:bg-primary/90 transition-colors" className="mt-4 px-6 py-3 bg-primary text-primary-foreground rounded-lg font-semibold hover:bg-primary/90 transition-colors"
onClick={() => window.open("https://docs.termix.site/install", "_blank")} onClick={() =>
window.open("https://docs.termix.site/install", "_blank")
}
> >
{t("mobile.viewMobileAppDocs")} {t("mobile.viewMobileAppDocs")}
</button> </button>

View File

@@ -58,14 +58,10 @@ interface LeftSidebarProps {
async function handleLogout() { async function handleLogout() {
try { try {
// Call backend logout endpoint to clear HttpOnly cookie and data session
await logoutUser(); await logoutUser();
// Reload the page to reset the application state
window.location.reload(); window.location.reload();
} catch (error) { } catch (error) {
console.error("Logout failed:", error); console.error("Logout failed:", error);
// Even if logout fails, reload the page to reset state
window.location.reload(); window.location.reload();
} }
} }