diff --git a/.npmrc b/.npmrc index 0c05da4..b6f27f1 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1 @@ engine-strict=true -resolution-mode=highest diff --git a/Caddyfile b/Caddyfile index 0dae9f3..821c804 100644 --- a/Caddyfile +++ b/Caddyfile @@ -1,5 +1,10 @@ :{$PORT:80} root * /app encode gzip zstd -try_files {path}.html {path} + +# SPA fallback for /admin path +handle /admin* { + try_files {path} /admin/index.html +} + file_server diff --git a/package-lock.json b/package-lock.json index 9d7e9e4..baa3bc4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "ipaddr.js": "^2.2.0", "js-xxhash": "^4.0.0", "json5": "^2.2.3", + "svelte-i18n": "^4.0.1", "svelte-jsoneditor": "^2.4.0", "unplugin-icons": "^22.1.0" }, @@ -24,7 +25,7 @@ "@skeletonlabs/tw-plugin": "^0.4.1", "@sveltejs/adapter-auto": "^4.0.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/kit": "^2.17.3", + "@sveltejs/kit": "2.49.2", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/forms": "0.5.10", "@tailwindcss/typography": "^0.5.16", @@ -38,7 +39,7 @@ "postcss": "^8.5.3", "prettier": "^3.5.2", "prettier-plugin-svelte": "^3.3.3", - "svelte": "^5.20.5", + "svelte": "5.42.1", "svelte-check": "^4.2.1", "tailwindcss": "3.4.17", "tslib": "^2.8.1", @@ -61,45 +62,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@antfu/install-pkg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.0.0.tgz", - "integrity": "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", "license": "MIT", "dependencies": { - "package-manager-detector": "^0.2.8", - "tinyexec": "^0.3.2" + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, - "node_modules/@antfu/utils": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-8.1.1.tgz", - "integrity": "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/@codemirror/autocomplete": { - "version": "6.18.4", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.4.tgz", - "integrity": "sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==", + "version": "6.20.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.1.tgz", + "integrity": "sha512-1cvg3Vz1dSSToCNlJfRA2WSI4ht3K+WplO0UMOgmUYPivCyy2oueZY6Lx7M9wThm7SDUBViRmuT+OG/i8+ON9A==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -109,21 +88,21 @@ } }, "node_modules/@codemirror/commands": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.0.tgz", - "integrity": "sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==", + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", - "@codemirror/state": "^6.4.0", + "@codemirror/state": "^6.6.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "node_modules/@codemirror/lang-json": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", - "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -131,23 +110,23 @@ } }, "node_modules/@codemirror/language": { - "version": "6.10.8", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.8.tgz", - "integrity": "sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==", + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.2.tgz", + "integrity": "sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", - "@lezer/common": "^1.1.0", + "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "node_modules/@codemirror/lint": { - "version": "6.8.4", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.4.tgz", - "integrity": "sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==", + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.5.tgz", + "integrity": "sha512-GElsbU9G7QT9xXhpUg1zWGmftA/7jamh+7+ydKRuT0ORpWS3wOSP0yT1FOlIZa7mIJjpVPipErsyvVqB9cfTFA==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", @@ -156,329 +135,313 @@ } }, "node_modules/@codemirror/search": { - "version": "6.5.8", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.8.tgz", - "integrity": "sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.6.0.tgz", + "integrity": "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", - "@codemirror/view": "^6.0.0", + "@codemirror/view": "^6.37.0", "crelt": "^1.0.5" } }, "node_modules/@codemirror/state": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.1.tgz", - "integrity": "sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", "license": "MIT", "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "node_modules/@codemirror/view": { - "version": "6.36.2", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.36.2.tgz", - "integrity": "sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==", + "version": "6.40.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.40.0.tgz", + "integrity": "sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==", "license": "MIT", "dependencies": { - "@codemirror/state": "^6.5.0", + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", + "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "aix" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", + "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", + "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", + "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", + "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", + "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", + "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", + "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", + "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", + "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", + "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", + "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", + "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", + "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", + "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", + "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", + "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", "cpu": [ "arm64" ], @@ -493,26 +456,25 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", + "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", "cpu": [ "arm64" ], @@ -527,94 +489,106 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", + "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "openbsd" ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", + "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", + "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", + "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", + "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": ">=12" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -631,9 +605,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -641,24 +615,31 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/config-array/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/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -667,9 +648,9 @@ } }, "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -679,10 +660,23 @@ "node": "*" } }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/core": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", - "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -693,20 +687,20 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", - "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", + "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -716,10 +710,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -727,10 +728,20 @@ "concat-map": "0.0.1" } }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -741,19 +752,22 @@ } }, "node_modules/@eslint/js": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz", - "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -761,13 +775,13 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz", - "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.12.0", + "@eslint/core": "^0.17.0", "levn": "^0.4.1" }, "engines": { @@ -775,30 +789,81 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz", - "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.8" + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.13.tgz", - "integrity": "sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.9" + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "license": "MIT" }, + "node_modules/@formatjs/ecma402-abstract": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.6.tgz", + "integrity": "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==", + "license": "MIT", + "dependencies": { + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/intl-localematcher": "0.6.2", + "decimal.js": "^10.4.3", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/fast-memoize": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.7.tgz", + "integrity": "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-messageformat-parser": { + "version": "2.11.4", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.11.4.tgz", + "integrity": "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/icu-skeleton-parser": "1.8.16", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/icu-skeleton-parser": { + "version": "1.8.16", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.16.tgz", + "integrity": "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ==", + "license": "MIT", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "tslib": "^2.8.0" + } + }, + "node_modules/@formatjs/intl-localematcher": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz", + "integrity": "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@fortawesome/fontawesome-common-types": { "version": "6.7.2", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz", @@ -843,33 +908,19 @@ } }, "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" + "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -885,9 +936,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", - "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -899,14 +950,14 @@ } }, "node_modules/@iconify/json": { - "version": "2.2.311", - "resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.311.tgz", - "integrity": "sha512-Qt9Q9MuyEfKpd+3027fzbCMhEkhNpUTc9mnUQImbVYr5BiyFxgAxwGcTl+oD6WEblzdnGU3KIXqH/Laekud35w==", + "version": "2.2.452", + "resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.452.tgz", + "integrity": "sha512-3gUSKSQ3UHRpuvk0GL5WdD3n+WR9MhvxjJ3cFjoBb44kD8yKC/esyxeOZfXdilRmJFvs1y8+j5DM6SIwCtMbXw==", "dev": true, "license": "MIT", "dependencies": { "@iconify/types": "*", - "pathe": "^1.1.2" + "pathe": "^2.0.3" } }, "node_modules/@iconify/types": { @@ -916,31 +967,14 @@ "license": "MIT" }, "node_modules/@iconify/utils": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-2.3.0.tgz", - "integrity": "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.0.tgz", + "integrity": "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==", "license": "MIT", "dependencies": { - "@antfu/install-pkg": "^1.0.0", - "@antfu/utils": "^8.1.0", + "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", - "debug": "^4.4.0", - "globals": "^15.14.0", - "kolorist": "^1.8.0", - "local-pkg": "^1.0.0", - "mlly": "^1.7.4" - } - }, - "node_modules/@iconify/utils/node_modules/globals": { - "version": "15.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", - "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "mlly": "^1.8.0" } }, "node_modules/@isaacs/cliui": { @@ -962,17 +996,23 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { @@ -984,25 +1024,16 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1043,18 +1074,18 @@ } }, "node_modules/@lezer/common": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", - "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.1.tgz", + "integrity": "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==", "license": "MIT" }, "node_modules/@lezer/highlight": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", - "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", "license": "MIT", "dependencies": { - "@lezer/common": "^1.0.0" + "@lezer/common": "^1.3.0" } }, "node_modules/@lezer/json": { @@ -1069,9 +1100,9 @@ } }, "node_modules/@lezer/lr": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", - "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.8.tgz", + "integrity": "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==", "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0" @@ -1122,17 +1153,17 @@ } }, "node_modules/@parcel/watcher": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", - "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", "hasInstallScript": true, "license": "MIT", "optional": true, "dependencies": { - "detect-libc": "^1.0.3", + "detect-libc": "^2.0.3", "is-glob": "^4.0.3", - "micromatch": "^4.0.5", - "node-addon-api": "^7.0.0" + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">= 10.0.0" @@ -1142,25 +1173,25 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.0", - "@parcel/watcher-darwin-arm64": "2.5.0", - "@parcel/watcher-darwin-x64": "2.5.0", - "@parcel/watcher-freebsd-x64": "2.5.0", - "@parcel/watcher-linux-arm-glibc": "2.5.0", - "@parcel/watcher-linux-arm-musl": "2.5.0", - "@parcel/watcher-linux-arm64-glibc": "2.5.0", - "@parcel/watcher-linux-arm64-musl": "2.5.0", - "@parcel/watcher-linux-x64-glibc": "2.5.0", - "@parcel/watcher-linux-x64-musl": "2.5.0", - "@parcel/watcher-win32-arm64": "2.5.0", - "@parcel/watcher-win32-ia32": "2.5.0", - "@parcel/watcher-win32-x64": "2.5.0" + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" } }, "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", - "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", "cpu": [ "arm64" ], @@ -1178,9 +1209,9 @@ } }, "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", - "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", "cpu": [ "arm64" ], @@ -1198,9 +1229,9 @@ } }, "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", - "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", "cpu": [ "x64" ], @@ -1218,9 +1249,9 @@ } }, "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", - "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", "cpu": [ "x64" ], @@ -1238,12 +1269,15 @@ } }, "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", - "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1258,12 +1292,15 @@ } }, "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", - "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", "cpu": [ "arm" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1278,12 +1315,15 @@ } }, "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", - "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1298,12 +1338,15 @@ } }, "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", - "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1318,12 +1361,15 @@ } }, "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", - "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1338,12 +1384,15 @@ } }, "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", - "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1358,9 +1407,9 @@ } }, "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", - "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", "cpu": [ "arm64" ], @@ -1378,9 +1427,9 @@ } }, "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", - "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", "cpu": [ "ia32" ], @@ -1398,9 +1447,9 @@ } }, "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", - "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", "cpu": [ "x64" ], @@ -1429,9 +1478,9 @@ } }, "node_modules/@polka/url": { - "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, "license": "MIT" }, @@ -1447,9 +1496,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.6.tgz", - "integrity": "sha512-+GcCXtOQoWuC7hhX1P00LqjjIiS/iOouHXhMdiDSnq/1DGTox4SpUvO52Xm+div6+106r+TcvOeo/cxvyEyTgg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", "cpu": [ "arm" ], @@ -1461,9 +1510,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.6.tgz", - "integrity": "sha512-E8+2qCIjciYUnCa1AiVF1BkRgqIGW9KzJeesQqVfyRITGQN+dFuoivO0hnro1DjT74wXLRZ7QF8MIbz+luGaJA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], @@ -1475,9 +1524,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.6.tgz", - "integrity": "sha512-z9Ib+OzqN3DZEjX7PDQMHEhtF+t6Mi2z/ueChQPLS/qUMKY7Ybn5A2ggFoKRNRh1q1T03YTQfBTQCJZiepESAg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], @@ -1489,9 +1538,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.6.tgz", - "integrity": "sha512-PShKVY4u0FDAR7jskyFIYVyHEPCPnIQY8s5OcXkdU8mz3Y7eXDJPdyM/ZWjkYdR2m0izD9HHWA8sGcXn+Qrsyg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], @@ -1503,9 +1552,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.6.tgz", - "integrity": "sha512-YSwyOqlDAdKqs0iKuqvRHLN4SrD2TiswfoLfvYXseKbL47ht1grQpq46MSiQAx6rQEN8o8URtpXARCpqabqxGQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", "cpu": [ "arm64" ], @@ -1517,9 +1566,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.6.tgz", - "integrity": "sha512-HEP4CgPAY1RxXwwL5sPFv6BBM3tVeLnshF03HMhJYCNc6kvSqBgTMmsEjb72RkZBAWIqiPUyF1JpEBv5XT9wKQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], @@ -1531,13 +1580,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.6.tgz", - "integrity": "sha512-88fSzjC5xeH9S2Vg3rPgXJULkHcLYMkh8faix8DX4h4TIAL65ekwuQMA/g2CXq8W+NJC43V6fUpYZNjaX3+IIg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1545,13 +1597,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.6.tgz", - "integrity": "sha512-wM4ztnutBqYFyvNeR7Av+reWI/enK9tDOTKNF+6Kk2Q96k9bwhDDOlnCUNRPvromlVXo04riSliMBs/Z7RteEg==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1559,13 +1614,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.6.tgz", - "integrity": "sha512-9RyprECbRa9zEjXLtvvshhw4CMrRa3K+0wcp3KME0zmBe1ILmvcVHnypZ/aIDXpRyfhSYSuN4EPdCCj5Du8FIA==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1573,123 +1631,237 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.6.tgz", - "integrity": "sha512-qTmklhCTyaJSB05S+iSovfo++EwnIEZxHkzv5dep4qoszUMX5Ca4WM4zAVUMbfdviLgCSQOu5oU8YoGk1s6M9Q==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.6.tgz", - "integrity": "sha512-4Qmkaps9yqmpjY5pvpkfOerYgKNUGzQpFxV6rnS7c/JfYbDSU0y6WpbbredB5cCpLFGJEqYX40WUmxMkwhWCjw==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.6.tgz", - "integrity": "sha512-Zsrtux3PuaxuBTX/zHdLaFmcofWGzaWW1scwLU3ZbW/X+hSsFbz9wDIp6XvnT7pzYRl9MezWqEqKy7ssmDEnuQ==", + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ - "ppc64" + "loong64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.6.tgz", - "integrity": "sha512-aK+Zp+CRM55iPrlyKiU3/zyhgzWBxLVrw2mwiQSYJRobCURb781+XstzvA8Gkjg/hbdQFuDw44aUOxVQFycrAg==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", "cpu": [ - "riscv64" + "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.6.tgz", - "integrity": "sha512-WoKLVrY9ogmaYPXwTH326+ErlCIgMmsoRSx6bO+l68YgJnlOXhygDYSZe/qbUJCSiCiZAQ+tKm88NcWuUXqOzw==", + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", "cpu": [ - "s390x" + "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.6.tgz", - "integrity": "sha512-Sht4aFvmA4ToHd2vFzwMFaQCiYm2lDFho5rPcvPBT5pCdC+GwHG6CMch4GQfmWTQ1SwRKS0dhDYb54khSrjDWw==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ - "x64" + "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.6.tgz", - "integrity": "sha512-zmmpOQh8vXc2QITsnCiODCDGXFC8LMi64+/oPpPx5qz3pqv0s6x46ps4xoycfUiVZps5PFn1gksZzo4RGTKT+A==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", "cpu": [ - "x64" + "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.6.tgz", - "integrity": "sha512-3/q1qUsO/tLqGBaD4uXsB6coVGB3usxw3qyeVb59aArCgedSF66MPdgRStUd7vbZOsko/CgVaY5fo2vkvPLWiA==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", "cpu": [ - "arm64" + "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ] }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.6.tgz", - "integrity": "sha512-oLHxuyywc6efdKVTxvc0135zPrRdtYVjtVD5GUm55I3ODxhU/PwkQFD97z16Xzxa1Fz0AEe4W/2hzRtd+IfpOA==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ - "ia32" + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" ], "dev": true, "license": "MIT", @@ -1699,9 +1871,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.6.tgz", - "integrity": "sha512-0PVwmgzZ8+TZ9oGBmdZoQVXflbvuwzN/HRclujpl4N/q3i+y0lqLw8n1bXA8ru3sApDjlmONaNAuYr38y1Kr9w==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", "cpu": [ "x64" ], @@ -1741,6 +1913,22 @@ "integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==", "license": "ISC" }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.8.tgz", + "integrity": "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, "node_modules/@sveltejs/adapter-auto": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-4.0.0.tgz", @@ -1755,9 +1943,9 @@ } }, "node_modules/@sveltejs/adapter-static": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.8.tgz", - "integrity": "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.10.tgz", + "integrity": "sha512-7D9lYFWJmB7zxZyTE/qxjksvMqzMuYrrsyh1f4AlZqeZeACPRySjbC3aFiY55wb1tWUaKOQG9PVbm74JcN2Iew==", "dev": true, "license": "MIT", "peerDependencies": { @@ -1765,17 +1953,19 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.17.3", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.17.3.tgz", - "integrity": "sha512-GcNaPDr0ti4O/TonPewkML2DG7UVXkSxPN3nPMlpmx0Rs4b2kVP4gymz98WEHlfzPXdd4uOOT1Js26DtieTNBQ==", + "version": "2.49.2", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.49.2.tgz", + "integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==", "dev": true, "license": "MIT", "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", + "acorn": "^8.14.1", "cookie": "^0.6.0", - "devalue": "^5.1.0", + "devalue": "^5.3.2", "esm-env": "^1.2.2", - "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", @@ -1790,9 +1980,15 @@ "node": ">=18.13" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", + "@opentelemetry/api": "^1.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "svelte": "^4.0.0 || ^5.0.0-next.0", - "vite": "^5.0.3 || ^6.0.0" + "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + } } }, "node_modules/@sveltejs/kit/node_modules/esm-env": { @@ -1803,18 +1999,18 @@ "license": "MIT" }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.0.3.tgz", - "integrity": "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.1.tgz", + "integrity": "sha512-Y1Cs7hhTc+a5E9Va/xwKlAJoariQyHY+5zBgCZg4PFWNYQ1nMN9sjK1zhw1gK69DuqVP++sht/1GZg1aRwmAXQ==", "dev": true, "license": "MIT", "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", - "debug": "^4.4.0", + "debug": "^4.4.1", "deepmerge": "^4.3.1", "kleur": "^4.1.5", - "magic-string": "^0.30.15", - "vitefu": "^1.0.4" + "magic-string": "^0.30.17", + "vitefu": "^1.0.6" }, "engines": { "node": "^18.0.0 || ^20.0.0 || >=22" @@ -1856,21 +2052,29 @@ } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", - "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", + "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==", "dev": true, "license": "MIT", "dependencies": { - "lodash.castarray": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", "postcss-selector-parser": "6.0.10" }, "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", @@ -1878,10 +2082,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/json-schema": { @@ -1892,38 +2103,36 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.13.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz", - "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==", + "version": "22.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.15.tgz", + "integrity": "sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.25.0.tgz", - "integrity": "sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.1.tgz", + "integrity": "sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/type-utils": "8.25.0", - "@typescript-eslint/utils": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.57.1", + "@typescript-eslint/type-utils": "8.57.1", + "@typescript-eslint/utils": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1933,23 +2142,46 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "@typescript-eslint/parser": "^8.57.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz", - "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.1.tgz", + "integrity": "sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.57.1", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/typescript-estree": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.1.tgz", + "integrity": "sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.57.1", + "@typescript-eslint/types": "^8.57.1", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1959,39 +2191,56 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz", - "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.1.tgz", + "integrity": "sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0" + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.1.tgz", + "integrity": "sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg==", + "dev": true, + "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.25.0.tgz", - "integrity": "sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.1.tgz", + "integrity": "sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.25.0", - "@typescript-eslint/utils": "8.25.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/typescript-estree": "8.57.1", + "@typescript-eslint/utils": "8.57.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2001,15 +2250,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz", - "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==", - "dev": true, + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.1.tgz", + "integrity": "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ==", + "devOptional": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2020,20 +2269,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz", - "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.1.tgz", + "integrity": "sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/visitor-keys": "8.25.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" + "@typescript-eslint/project-service": "8.57.1", + "@typescript-eslint/tsconfig-utils": "8.57.1", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/visitor-keys": "8.57.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2043,20 +2293,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.25.0.tgz", - "integrity": "sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.1.tgz", + "integrity": "sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.25.0", - "@typescript-eslint/types": "8.25.0", - "@typescript-eslint/typescript-estree": "8.25.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.57.1", + "@typescript-eslint/types": "8.57.1", + "@typescript-eslint/typescript-estree": "8.57.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2066,19 +2316,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.25.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz", - "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==", + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.1.tgz", + "integrity": "sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.25.0", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.57.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2089,27 +2339,28 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@vitest/expect": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.7.tgz", - "integrity": "sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.7", - "@vitest/utils": "3.0.7", + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -2118,13 +2369,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.7.tgz", - "integrity": "sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.0.7", + "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -2133,7 +2384,7 @@ }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "peerDependenciesMeta": { "msw": { @@ -2144,10 +2395,20 @@ } } }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/@vitest/pretty-format": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.7.tgz", - "integrity": "sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -2158,34 +2419,28 @@ } }, "node_modules/@vitest/runner": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.7.tgz", - "integrity": "sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.0.7", - "pathe": "^2.0.3" + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/runner/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/@vitest/snapshot": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.7.tgz", - "integrity": "sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.7", + "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -2193,35 +2448,28 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/snapshot/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/@vitest/spy": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.7.tgz", - "integrity": "sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { - "tinyspy": "^3.0.2" + "tinyspy": "^4.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.7.tgz", - "integrity": "sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.0.7", - "loupe": "^3.1.3", + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" }, "funding": { @@ -2229,9 +2477,9 @@ } }, "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -2250,19 +2498,10 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-typescript": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/acorn-typescript/-/acorn-typescript-1.4.13.tgz", - "integrity": "sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==", - "license": "MIT", - "peerDependencies": { - "acorn": ">=8.9.0" - } - }, "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": { @@ -2277,9 +2516,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -2326,6 +2565,19 @@ "node": ">= 8" } }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -2341,9 +2593,9 @@ "license": "Python-2.0" }, "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -2416,11 +2668,27 @@ } }, "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==", + "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" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.9", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.9.tgz", + "integrity": "sha512-OZd0e2mU11ClX8+IdXe3r0dbqMEznRiT4TfbhYIbcRPZkqJ7Qwer8ij3GZAmLsRKa+II9V1v5czCkvmHH3XZBg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } }, "node_modules/binary-extensions": { "version": "2.3.0", @@ -2436,20 +2704,23 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "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": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -2459,9 +2730,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -2479,10 +2750,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -2522,9 +2794,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "version": "1.0.30001780", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", + "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", "dev": true, "funding": [ { @@ -2543,9 +2815,9 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", "dev": true, "license": "MIT", "dependencies": { @@ -2556,7 +2828,7 @@ "pathval": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/chalk": { @@ -2577,9 +2849,9 @@ } }, "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", "dev": true, "license": "MIT", "engines": { @@ -2601,6 +2873,22 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/cli-color": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.4.tgz", + "integrity": "sha512-zlnpg0jNcibNrO7GG9IeHH7maWFeCz+Ja1wx/7tZNU5ASSSSZ+/qZciM0/LHCYxSdqv5h2sdbQ/PXYdOuetXvA==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.64", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2611,9 +2899,9 @@ } }, "node_modules/codemirror-wrapped-line-indent": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/codemirror-wrapped-line-indent/-/codemirror-wrapped-line-indent-1.0.8.tgz", - "integrity": "sha512-5UwuHCz4oAZuvot1DbfFxSxJacTESdNGa/KpJD7HfpVpDAJdgB1vV9OG4b4pkJqPWuOfIpFLTQEKS85kTpV+XA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/codemirror-wrapped-line-indent/-/codemirror-wrapped-line-indent-1.0.9.tgz", + "integrity": "sha512-oc976hHLt35u6Ojbhub+IWOxEpapZSqYieLEdGhsgFZ4rtYQtdb5KjxzgjCCyVe3t0yk+a6hmaIOEsjU/tZRxQ==", "license": "MIT", "peerDependencies": { "@codemirror/language": "^6.9.0", @@ -2659,9 +2947,9 @@ "license": "MIT" }, "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", "license": "MIT" }, "node_modules/cookie": { @@ -2722,10 +3010,23 @@ "node": ">=4" } }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2739,6 +3040,12 @@ } } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -2760,30 +3067,25 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "optional": true, - "bin": { - "detect-libc": "bin/detect-libc.js" - }, "engines": { - "node": ">=0.10" + "node": ">=8" } }, "node_modules/devalue": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", - "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", - "dev": true, + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz", + "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==", "license": "MIT" }, "node_modules/didyoumean": { @@ -2839,9 +3141,9 @@ } }, "node_modules/dompurify": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.4.tgz", - "integrity": "sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", + "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -2855,9 +3157,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.76", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", - "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", + "version": "1.5.321", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.321.tgz", + "integrity": "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==", "dev": true, "license": "ISC" }, @@ -2869,9 +3171,9 @@ "license": "MIT" }, "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -2882,64 +3184,113 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "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==", "dev": true, "license": "MIT" }, - "node_modules/esbuild": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", - "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", - "dev": true, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" }, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.0", - "@esbuild/android-arm": "0.25.0", - "@esbuild/android-arm64": "0.25.0", - "@esbuild/android-x64": "0.25.0", - "@esbuild/darwin-arm64": "0.25.0", - "@esbuild/darwin-x64": "0.25.0", - "@esbuild/freebsd-arm64": "0.25.0", - "@esbuild/freebsd-x64": "0.25.0", - "@esbuild/linux-arm": "0.25.0", - "@esbuild/linux-arm64": "0.25.0", - "@esbuild/linux-ia32": "0.25.0", - "@esbuild/linux-loong64": "0.25.0", - "@esbuild/linux-mips64el": "0.25.0", - "@esbuild/linux-ppc64": "0.25.0", - "@esbuild/linux-riscv64": "0.25.0", - "@esbuild/linux-s390x": "0.25.0", - "@esbuild/linux-x64": "0.25.0", - "@esbuild/netbsd-arm64": "0.25.0", - "@esbuild/netbsd-x64": "0.25.0", - "@esbuild/openbsd-arm64": "0.25.0", - "@esbuild/openbsd-x64": "0.25.0", - "@esbuild/sunos-x64": "0.25.0", - "@esbuild/win32-arm64": "0.25.0", - "@esbuild/win32-ia32": "0.25.0", - "@esbuild/win32-x64": "0.25.0" + "node": ">=0.10" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, - "node_modules/escape-string-regexp": { + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "license": "ISC", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/esbuild": { + "version": "0.19.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", + "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.19.12", + "@esbuild/android-arm": "0.19.12", + "@esbuild/android-arm64": "0.19.12", + "@esbuild/android-x64": "0.19.12", + "@esbuild/darwin-arm64": "0.19.12", + "@esbuild/darwin-x64": "0.19.12", + "@esbuild/freebsd-arm64": "0.19.12", + "@esbuild/freebsd-x64": "0.19.12", + "@esbuild/linux-arm": "0.19.12", + "@esbuild/linux-arm64": "0.19.12", + "@esbuild/linux-ia32": "0.19.12", + "@esbuild/linux-loong64": "0.19.12", + "@esbuild/linux-mips64el": "0.19.12", + "@esbuild/linux-ppc64": "0.19.12", + "@esbuild/linux-riscv64": "0.19.12", + "@esbuild/linux-s390x": "0.19.12", + "@esbuild/linux-x64": "0.19.12", + "@esbuild/netbsd-x64": "0.19.12", + "@esbuild/openbsd-x64": "0.19.12", + "@esbuild/sunos-x64": "0.19.12", + "@esbuild/win32-arm64": "0.19.12", + "@esbuild/win32-ia32": "0.19.12", + "@esbuild/win32-x64": "0.19.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", @@ -2953,32 +3304,32 @@ } }, "node_modules/eslint": { - "version": "9.21.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz", - "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.19.2", - "@eslint/core": "^0.12.0", - "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.21.0", - "@eslint/plugin-kit": "^0.2.7", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", + "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.2.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2990,7 +3341,7 @@ "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -3012,61 +3363,48 @@ } } }, - "node_modules/eslint-compat-utils": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.6.4.tgz", - "integrity": "sha512-/u+GQt8NMfXO8w17QendT4gvO5acfxQsAKirAt0LVxDnr2N8YLCVbregaNc/Yhp7NM128DwCaRvr8PLDfeNkQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, "node_modules/eslint-config-prettier": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.2.tgz", - "integrity": "sha512-1105/17ZIMjmCOJOPNfVdbXafLCLj3hPmkmB7dLgt7XsQ/zkxSuDerE/xgO3RxoHysR1N1whmquY0lSn2O0VLg==", + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", "bin": { - "eslint-config-prettier": "build/bin/cli.js" + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" }, "peerDependencies": { "eslint": ">=7.0.0" } }, "node_modules/eslint-plugin-svelte": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.0.2.tgz", - "integrity": "sha512-+0QglmWNryvXXxRQKzLF3i+AreTsueCw7PBb0nGVBq+F9HoYqAjQeJ/9N6vFAtjMjK3wgsETrLVyBKPdeufN6Q==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-svelte/-/eslint-plugin-svelte-3.15.2.tgz", + "integrity": "sha512-k4Nsjs3bHujeEnnckoTM4mFYR1e8Mb9l2rTwNdmYiamA+Tjzn8X+2F+fuSP2w4VbXYhn2bmySyACQYdmUDW2Cg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.1", + "@eslint-community/eslint-utils": "^4.6.1", "@jridgewell/sourcemap-codec": "^1.5.0", - "eslint-compat-utils": "^0.6.4", "esutils": "^2.0.3", - "known-css-properties": "^0.35.0", + "globals": "^16.0.0", + "known-css-properties": "^0.37.0", "postcss": "^8.4.49", "postcss-load-config": "^3.1.4", "postcss-safe-parser": "^7.0.0", "semver": "^7.6.3", - "svelte-eslint-parser": "^1.0.0" + "svelte-eslint-parser": "^1.4.0" }, "engines": { - "node": "^18.20.4 || ^20.18.0 || >=22.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://github.com/sponsors/ota-meshi" }, "peerDependencies": { - "eslint": "^8.57.1 || ^9.0.0", + "eslint": "^8.57.1 || ^9.0.0 || ^10.0.0", "svelte": "^3.37.0 || ^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { @@ -3075,10 +3413,23 @@ } } }, + "node_modules/eslint-plugin-svelte/node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/eslint-scope": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", - "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -3105,10 +3456,17 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/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/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -3117,9 +3475,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3129,10 +3487,20 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { @@ -3149,16 +3517,31 @@ "dev": true, "license": "MIT" }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3168,9 +3551,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3181,9 +3564,9 @@ } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -3194,12 +3577,20 @@ } }, "node_modules/esrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.3.tgz", - "integrity": "sha512-Xddc1RsoFJ4z9nR7W7BFaEPIp4UXoeQ0+077UdWLxbafMQFyU79sQJMk7kxNgRwQ9/aVgaKacCHC2pUACGwmYw==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.5.tgz", + "integrity": "sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "peerDependencies": { + "@typescript-eslint/types": "^8.2.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/types": { + "optional": true + } } }, "node_modules/esrecurse": { @@ -3226,14 +3617,10 @@ } }, "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", @@ -3245,16 +3632,41 @@ "node": ">=0.10.0" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "node_modules/expect-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", - "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "license": "MIT" + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3306,9 +3718,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "funding": [ { "type": "github", @@ -3322,15 +3734,33 @@ "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", @@ -3348,7 +3778,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -3389,20 +3819,20 @@ } }, "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -3452,9 +3882,10 @@ } }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { @@ -3485,6 +3916,39 @@ "node": ">=10.13.0" } }, + "node_modules/glob/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/glob/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/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -3498,11 +3962,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", + "license": "MIT" + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "license": "MIT" }, "node_modules/has-flag": { @@ -3538,9 +4007,9 @@ } }, "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -3548,15 +4017,15 @@ } }, "node_modules/immutable": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", - "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", + "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", "license": "MIT" }, "node_modules/immutable-json-patch": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/immutable-json-patch/-/immutable-json-patch-6.0.1.tgz", - "integrity": "sha512-BHL/cXMjwFZlTOffiWNdY8ZTvNyYLrutCnWxrcKPHr5FqpAb6vsO6WWSPnVSys3+DruFN6lhHJJPHi8uELQL5g==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/immutable-json-patch/-/immutable-json-patch-6.0.2.tgz", + "integrity": "sha512-KwCA5DXJiyldda8SPha1zB+6+vbEi5/jRRcYii/6yFXlyu9ZjiSH/wPq8Ri2Hk8iGjjTMcHW3Z21S4MOpl7sOw==", "license": "ISC" }, "node_modules/import-fresh": { @@ -3577,9 +4046,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", "dev": true, "license": "MIT", "funding": { @@ -3597,10 +4066,22 @@ "node": ">=0.8.19" } }, + "node_modules/intl-messageformat": { + "version": "10.7.18", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.18.tgz", + "integrity": "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g==", + "license": "BSD-3-Clause", + "dependencies": { + "@formatjs/ecma402-abstract": "2.3.6", + "@formatjs/fast-memoize": "2.2.7", + "@formatjs/icu-messageformat-parser": "2.11.4", + "tslib": "^2.8.0" + } + }, "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", + "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", "license": "MIT", "engines": { "node": ">= 10" @@ -3672,12 +4153,18 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", + "license": "MIT" + }, "node_modules/is-reference": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", @@ -3729,6 +4216,13 @@ "node": ">= 0.6.0" } }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-xxhash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-xxhash/-/js-xxhash-4.0.0.tgz", @@ -3739,9 +4233,9 @@ } }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -3800,9 +4294,9 @@ } }, "node_modules/jsonpath-plus": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.2.0.tgz", - "integrity": "sha512-T9V+8iNYKFL2n2rF+w02LBOT2JjDnTjioaNFrxRy0Bv1y/hNsqR/EBK7Ojy2ythRHwmz2cRIls+9JitQGZC/sw==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", + "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", "license": "MIT", "dependencies": { "@jsep-plugin/assignment": "^1.3.0", @@ -3818,9 +4312,9 @@ } }, "node_modules/jsonrepair": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.11.2.tgz", - "integrity": "sha512-ejydGcTq0qKk1r0NUBwjtvswbPFhs19+QEfwSeGwB8KJZ59W7/AOFmQh04c68mkJ+2hGk+OkOmkr2bKG4tGlLQ==", + "version": "3.13.3", + "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.13.3.tgz", + "integrity": "sha512-BTznj0owIt2CBAH/LTo7+1I5pMvl1e1033LRl/HUowlZmJOIhzC0zbX5bxMngLkfT4WnzPP26QnW5wMr2g9tsQ==", "license": "ISC", "bin": { "jsonrepair": "bin/cli.js" @@ -3847,18 +4341,12 @@ } }, "node_modules/known-css-properties": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.35.0.tgz", - "integrity": "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==", + "version": "0.37.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.37.0.tgz", + "integrity": "sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==", "dev": true, "license": "MIT" }, - "node_modules/kolorist": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", - "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", - "license": "MIT" - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3891,13 +4379,14 @@ "license": "MIT" }, "node_modules/local-pkg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.0.0.tgz", - "integrity": "sha512-bbgPw/wmroJsil/GgL4qjDzs5YLTBMQ99weRsok1XCDccQeehbHA/I1oRvk2NPtr7KGZgT/Y5tPRnAtMqeG2Kg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz", + "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==", "license": "MIT", "dependencies": { - "mlly": "^1.7.3", - "pkg-types": "^1.3.0" + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" }, "engines": { "node": ">=14" @@ -3929,23 +4418,9 @@ } }, "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "license": "MIT" - }, - "node_modules/lodash.castarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", - "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz", + "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, "node_modules/lodash.merge": { @@ -3956,9 +4431,9 @@ "license": "MIT" }, "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", "dev": true, "license": "MIT" }, @@ -3969,13 +4444,22 @@ "dev": true, "license": "ISC" }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/mdn-data": { @@ -3991,6 +4475,25 @@ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", "license": "MIT" }, + "node_modules/memoizee": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.17.tgz", + "integrity": "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "es5-ext": "^0.10.64", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4005,7 +4508,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -4015,6 +4518,19 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/mini-svg-data-uri": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", @@ -4026,63 +4542,73 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/mlly": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.4.tgz", - "integrity": "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", "license": "MIT", "dependencies": { - "acorn": "^8.14.0", - "pathe": "^2.0.1", - "pkg-types": "^1.3.0", - "ufo": "^1.5.4" + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" } }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", "license": "MIT" }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/mrmime": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", - "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", "engines": { @@ -4108,9 +4634,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { @@ -4139,17 +4665,23 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "license": "MIT" }, - "node_modules/node-addon-api": { - "version": "7.1.1", + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, + "node_modules/node-addon-api": { + "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT", "optional": true }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, @@ -4251,9 +4783,9 @@ "license": "BlueOak-1.0.0" }, "node_modules/package-manager-detector": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.9.tgz", - "integrity": "sha512-+vYvA/Y31l8Zk8dwxHhL3JfTuHPm6tlxM2A3GeQyl7ovYnSp1+mzAxClxaOr0qO1TtPxbQxetI7v5XqKLJZk7Q==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.6.0.tgz", + "integrity": "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==", "license": "MIT" }, "node_modules/parent-module": { @@ -4270,13 +4802,13 @@ } }, "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^4.5.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -4341,16 +4873,15 @@ } }, "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "license": "MIT" }, "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", "dev": true, "license": "MIT", "engines": { @@ -4365,13 +4896,12 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "devOptional": true, + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -4388,9 +4918,9 @@ } }, "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, "license": "MIT", "engines": { @@ -4398,26 +4928,20 @@ } }, "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", "license": "MIT", "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" } }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "license": "MIT" - }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, "funding": [ { @@ -4435,7 +4959,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -4462,10 +4986,20 @@ } }, "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" @@ -4473,10 +5007,6 @@ "engines": { "node": "^12 || ^14 || >= 16" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.4.21" } @@ -4512,9 +5042,9 @@ } }, "node_modules/postcss-load-config/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", "dev": true, "license": "ISC", "engines": { @@ -4647,9 +5177,9 @@ } }, "node_modules/prettier": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", - "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", "bin": { @@ -4663,9 +5193,9 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.3.tgz", - "integrity": "sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.1.tgz", + "integrity": "sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4720,6 +5250,22 @@ "node": ">=18" } }, + "node_modules/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4752,12 +5298,12 @@ } }, "node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "license": "MIT", "engines": { - "node": ">= 14.16.0" + "node": ">= 14.18.0" }, "funding": { "type": "individual", @@ -4774,13 +5320,13 @@ } }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -4805,9 +5351,9 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -4816,13 +5362,13 @@ } }, "node_modules/rollup": { - "version": "4.34.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.6.tgz", - "integrity": "sha512-wc2cBWqJgkU3Iz5oztRkQbfVkbxoz5EhnCGOrnJvnLnQ7O0WhQUYyv18qQI79O8L7DdHrrlJNeCHd4VGpnaXKQ==", + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -4832,25 +5378,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.6", - "@rollup/rollup-android-arm64": "4.34.6", - "@rollup/rollup-darwin-arm64": "4.34.6", - "@rollup/rollup-darwin-x64": "4.34.6", - "@rollup/rollup-freebsd-arm64": "4.34.6", - "@rollup/rollup-freebsd-x64": "4.34.6", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.6", - "@rollup/rollup-linux-arm-musleabihf": "4.34.6", - "@rollup/rollup-linux-arm64-gnu": "4.34.6", - "@rollup/rollup-linux-arm64-musl": "4.34.6", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.6", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.6", - "@rollup/rollup-linux-riscv64-gnu": "4.34.6", - "@rollup/rollup-linux-s390x-gnu": "4.34.6", - "@rollup/rollup-linux-x64-gnu": "4.34.6", - "@rollup/rollup-linux-x64-musl": "4.34.6", - "@rollup/rollup-win32-arm64-msvc": "4.34.6", - "@rollup/rollup-win32-ia32-msvc": "4.34.6", - "@rollup/rollup-win32-x64-msvc": "4.34.6", + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" } }, @@ -4882,7 +5434,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, "license": "MIT", "dependencies": { "mri": "^1.1.0" @@ -4892,13 +5443,13 @@ } }, "node_modules/sass": { - "version": "1.83.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz", - "integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==", + "version": "1.98.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz", + "integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==", "license": "MIT", "dependencies": { "chokidar": "^4.0.0", - "immutable": "^5.0.2", + "immutable": "^5.1.5", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -4912,9 +5463,9 @@ } }, "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { @@ -4925,9 +5476,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "dev": true, "license": "MIT" }, @@ -4975,9 +5526,9 @@ } }, "node_modules/sirv": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz", - "integrity": "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dev": true, "license": "MIT", "dependencies": { @@ -5006,9 +5557,9 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", - "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, "license": "MIT" }, @@ -5077,13 +5628,13 @@ } }, "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" @@ -5129,25 +5680,38 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/style-mod": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", - "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", "license": "MIT" }, "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", - "glob": "^10.3.10", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { @@ -5185,21 +5749,23 @@ } }, "node_modules/svelte": { - "version": "5.20.5", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.20.5.tgz", - "integrity": "sha512-dpu2lTPVsAAgZFKpF7A9741sBCdXGogfxFU4aQeVgun7GVNCSVheTzj0FsT7g9OsLhBaMX4lKLwVIvmzQGytmQ==", + "version": "5.42.1", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.42.1.tgz", + "integrity": "sha512-gc0yfYY7OcuFbK2k/R/cHYYoN7A3SvYsnWHiWYayEV7OZpjSKyVHA1Ex0tW5eEbfQui6guN+sZ2whvhuz+qHpg==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", + "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", - "acorn-typescript": "^1.4.13", "aria-query": "^5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", + "devalue": "^5.6.4", "esm-env": "^1.2.1", - "esrap": "^1.4.3", + "esrap": "^2.1.0", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -5219,9 +5785,9 @@ } }, "node_modules/svelte-check": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.2.1.tgz", - "integrity": "sha512-e49SU1RStvQhoipkQ/aonDhHnG3qxHSBtNfBRb9pxVXoa+N7qybAo32KgA9wEb2PCYFNaDg7bZCdhLD1vHpdYA==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.5.tgz", + "integrity": "sha512-1bSwIRCvvmSHrlK52fOlZmVtUZgil43jNL/2H18pRpa+eQjzGt6e3zayxhp1S7GajPFKNM/2PMCG+DZFHlG9fw==", "dev": true, "license": "MIT", "dependencies": { @@ -5257,25 +5823,10 @@ } } }, - "node_modules/svelte-check/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/svelte-eslint-parser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.0.0.tgz", - "integrity": "sha512-diZzpeeFhAxormeIhmRS4vXx98GG6T7Dq5y1a6qffqs/5MBrBqqDg8bj88iEohp6bvhU4MIABJmOTa0gXWcbSQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-1.6.0.tgz", + "integrity": "sha512-qoB1ehychT6OxEtQAqc/guSqLS20SlA53Uijl7x375s8nlUT0lb9ol/gzraEEatQwsyPTJo87s2CmKL9Xab+Uw==", "dev": true, "license": "MIT", "dependencies": { @@ -5284,10 +5835,12 @@ "espree": "^10.0.0", "postcss": "^8.4.49", "postcss-scss": "^4.0.9", - "postcss-selector-parser": "^7.0.0" + "postcss-selector-parser": "^7.0.0", + "semver": "^7.7.2" }, "engines": { - "node": "^18.20.4 || ^20.18.0 || >=22.10.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0", + "pnpm": "10.30.3" }, "funding": { "url": "https://github.com/sponsors/ota-meshi" @@ -5302,9 +5855,9 @@ } }, "node_modules/svelte-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5315,9 +5868,9 @@ } }, "node_modules/svelte-eslint-parser/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "dev": true, "license": "MIT", "dependencies": { @@ -5338,6 +5891,30 @@ "@floating-ui/dom": "^1.5.3" } }, + "node_modules/svelte-i18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svelte-i18n/-/svelte-i18n-4.0.1.tgz", + "integrity": "sha512-jaykGlGT5PUaaq04JWbJREvivlCnALtT+m87Kbm0fxyYHynkQaxQMnIKHLm2WeIuBRoljzwgyvz0Z6/CMwfdmQ==", + "license": "MIT", + "dependencies": { + "cli-color": "^2.0.3", + "deepmerge": "^4.2.2", + "esbuild": "^0.19.2", + "estree-walker": "^2", + "intl-messageformat": "^10.5.3", + "sade": "^1.8.1", + "tiny-glob": "^0.2.9" + }, + "bin": { + "svelte-i18n": "dist/cli.js" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "svelte": "^3 || ^4 || ^5" + } + }, "node_modules/svelte-jsoneditor": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/svelte-jsoneditor/-/svelte-jsoneditor-2.4.0.tgz", @@ -5378,9 +5955,9 @@ } }, "node_modules/svelte-jsoneditor/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -5409,9 +5986,9 @@ } }, "node_modules/svelte/node_modules/esm-env": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz", - "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", "license": "MIT" }, "node_modules/tailwindcss": { @@ -5503,6 +6080,19 @@ "url": "https://github.com/sponsors/antonk52" } }, + "node_modules/tailwindcss/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tailwindcss/node_modules/postcss-load-config": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", @@ -5589,6 +6179,29 @@ "node": ">=0.8" } }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/tiny-glob": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", + "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", + "license": "MIT", + "dependencies": { + "globalyzer": "0.1.0", + "globrex": "^0.1.2" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -5597,15 +6210,35 @@ "license": "MIT" }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "license": "MIT" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } }, "node_modules/tinypool": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -5623,9 +6256,9 @@ } }, "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", "dev": true, "license": "MIT", "engines": { @@ -5636,7 +6269,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -5656,9 +6289,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { @@ -5681,6 +6314,12 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5695,9 +6334,9 @@ } }, "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5709,25 +6348,27 @@ } }, "node_modules/ufo": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz", - "integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", + "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", "license": "MIT" }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, "node_modules/unplugin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.2.0.tgz", - "integrity": "sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw==", + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", "license": "MIT", "dependencies": { - "acorn": "^8.14.0", + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" }, "engines": { @@ -5735,16 +6376,16 @@ } }, "node_modules/unplugin-icons": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-22.1.0.tgz", - "integrity": "sha512-ect2ZNtk1Zgwb0NVHd0C1IDW/MV+Jk/xaq4t8o6rYdVS3+L660ZdD5kTSQZvsgdwCvquRw+/wYn75hsweRjoIA==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-22.5.0.tgz", + "integrity": "sha512-MBlMtT5RuMYZy4TZgqUL2OTtOdTUVsS1Mhj6G1pEzMlFJlEnq6mhUfoIt45gBWxHcsOdXJDWLg3pRZ+YmvAVWQ==", "license": "MIT", "dependencies": { - "@antfu/install-pkg": "^1.0.0", - "@iconify/utils": "^2.3.0", - "debug": "^4.4.0", - "local-pkg": "^1.0.0", - "unplugin": "^2.2.0" + "@antfu/install-pkg": "^1.1.0", + "@iconify/utils": "^3.0.2", + "debug": "^4.4.3", + "local-pkg": "^1.1.2", + "unplugin": "^2.3.10" }, "funding": { "url": "https://github.com/sponsors/antfu" @@ -5779,9 +6420,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -5800,7 +6441,7 @@ "license": "MIT", "dependencies": { "escalade": "^3.2.0", - "picocolors": "^1.1.0" + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -5836,15 +6477,18 @@ } }, "node_modules/vite": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz", - "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", + "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -5908,17 +6552,17 @@ } }, "node_modules/vite-node": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.7.tgz", - "integrity": "sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, "license": "MIT", "dependencies": { "cac": "^6.7.14", - "debug": "^4.4.0", - "es-module-lexer": "^1.6.0", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0" + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" @@ -5930,13 +6574,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/vite-node/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, "node_modules/vite-plugin-tailwind-purgecss": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/vite-plugin-tailwind-purgecss/-/vite-plugin-tailwind-purgecss-0.3.5.tgz", @@ -5956,9 +6593,9 @@ } }, "node_modules/vite-plugin-tailwind-purgecss/node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { @@ -5968,18 +6605,452 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, "node_modules/vitefu": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.5.tgz", - "integrity": "sha512-h4Vflt9gxODPFNGPwp4zAMZRpZR7eslzwH2c5hn5kNZ5rhnKyRJ50U+yGCdc2IRaBs8O4haIgLNGrV5CrpMsCA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz", + "integrity": "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==", "dev": true, "license": "MIT", "workspaces": [ "tests/deps/*", - "tests/projects/*" + "tests/projects/*", + "tests/projects/workspace/packages/*" ], "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "peerDependenciesMeta": { "vite": { @@ -5988,31 +7059,34 @@ } }, "node_modules/vitest": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.7.tgz", - "integrity": "sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.0.7", - "@vitest/mocker": "3.0.7", - "@vitest/pretty-format": "^3.0.7", - "@vitest/runner": "3.0.7", - "@vitest/snapshot": "3.0.7", - "@vitest/spy": "3.0.7", - "@vitest/utils": "3.0.7", + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", - "debug": "^4.4.0", - "expect-type": "^1.1.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.0", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", - "tinypool": "^1.0.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.7", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -6028,8 +7102,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.7", - "@vitest/ui": "3.0.7", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, @@ -6057,10 +7131,10 @@ } } }, - "node_modules/vitest/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "node_modules/vitest/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, "license": "MIT" }, @@ -6202,9 +7276,9 @@ } }, "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { @@ -6215,16 +7289,19 @@ } }, "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yocto-queue": { @@ -6241,9 +7318,9 @@ } }, "node_modules/zimmerframe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.2.tgz", - "integrity": "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", "license": "MIT" } } diff --git a/package.json b/package.json index 6540639..0d4ea40 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "dev": "vite dev", "build": "vite build", "preview": "vite preview", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "i18n:check": "node ./scripts/i18n.mjs check", + "i18n:sync": "node ./scripts/i18n.mjs sync", + "check": "npm run i18n:check && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "test": "vitest", "lint": "prettier --plugin-search-dir . --check . && eslint .", @@ -18,7 +20,7 @@ "@skeletonlabs/tw-plugin": "^0.4.1", "@sveltejs/adapter-auto": "^4.0.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/kit": "^2.17.3", + "@sveltejs/kit": "2.49.2", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/forms": "0.5.10", "@tailwindcss/typography": "^0.5.16", @@ -32,7 +34,7 @@ "postcss": "^8.5.3", "prettier": "^3.5.2", "prettier-plugin-svelte": "^3.3.3", - "svelte": "^5.20.5", + "svelte": "5.42.1", "svelte-check": "^4.2.1", "tailwindcss": "3.4.17", "tslib": "^2.8.1", @@ -50,6 +52,7 @@ "ipaddr.js": "^2.2.0", "js-xxhash": "^4.0.0", "json5": "^2.2.3", + "svelte-i18n": "^4.0.1", "svelte-jsoneditor": "^2.4.0", "unplugin-icons": "^22.1.0" } diff --git a/scripts/i18n.mjs b/scripts/i18n.mjs new file mode 100644 index 0000000..e4c05eb --- /dev/null +++ b/scripts/i18n.mjs @@ -0,0 +1,223 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { execFileSync } from 'node:child_process'; + +const rootDir = process.cwd(); +const localesDir = path.join(rootDir, 'src', 'lib', 'locales'); +const srcDir = path.join(rootDir, 'src'); +const sourceLocale = 'en'; + +function readJson(filePath) { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +function writeJson(filePath, data) { + const formatted = `${JSON.stringify(data, null, 2)}\n`; + fs.writeFileSync(filePath, formatted); +} + +function isPlainObject(value) { + return value !== null && typeof value === 'object' && !Array.isArray(value); +} + +function flattenObject(value, prefix = '', result = {}) { + for (const [key, nestedValue] of Object.entries(value)) { + const nextKey = prefix ? `${prefix}.${key}` : key; + if (isPlainObject(nestedValue)) { + flattenObject(nestedValue, nextKey, result); + } else { + result[nextKey] = nestedValue; + } + } + + return result; +} + +function cloneValue(value) { + if (Array.isArray(value)) { + return value.map(cloneValue); + } + + if (isPlainObject(value)) { + return Object.fromEntries(Object.entries(value).map(([key, nestedValue]) => [key, cloneValue(nestedValue)])); + } + + return value; +} + +function buildSyncedLocale(sourceShape, targetValue) { + if (!isPlainObject(sourceShape) || !isPlainObject(targetValue)) { + return cloneValue(isPlainObject(targetValue) ? targetValue : sourceShape); + } + + const synced = {}; + + for (const [key, sourceNestedValue] of Object.entries(sourceShape)) { + const targetNestedValue = targetValue[key]; + if (isPlainObject(sourceNestedValue)) { + synced[key] = buildSyncedLocale(sourceNestedValue, isPlainObject(targetNestedValue) ? targetNestedValue : {}); + } else if (targetNestedValue !== undefined) { + synced[key] = targetNestedValue; + } else { + synced[key] = ''; + } + } + + return synced; +} + +function listLocaleFiles() { + return fs + .readdirSync(localesDir) + .filter((fileName) => fileName.endsWith('.json')) + .sort(); +} + +function getLocaleName(fileName) { + return path.basename(fileName, '.json'); +} + +function getReferencedTranslationKeys() { + try { + const output = execFileSync( + 'rg', + [ + '-o', + '--no-filename', + "(?<=\\$_\\('|\\$_\\(\")(?:[A-Za-z0-9_]+\\.)+[A-Za-z0-9_]+", + srcDir, + '-g', + '!src/lib/locales/*', + '-P', + ], + { cwd: rootDir, encoding: 'utf8' } + ); + + return [...new Set(output.match(/(?:[A-Za-z0-9_]+\.)+[A-Za-z0-9_]+/g) ?? [])].sort(); + } catch (error) { + if (error.status === 1) { + return []; + } + + throw error; + } +} + +function getLocales() { + const locales = new Map(); + for (const fileName of listLocaleFiles()) { + const localeName = getLocaleName(fileName); + locales.set(localeName, { + fileName, + filePath: path.join(localesDir, fileName), + data: readJson(path.join(localesDir, fileName)), + }); + } + + return locales; +} + +function compareKeys(sourceKeys, targetKeys) { + return { + missing: sourceKeys.filter((key) => !targetKeys.includes(key)), + extra: targetKeys.filter((key) => !sourceKeys.includes(key)), + }; +} + +function collectCheckProblems(locales) { + const problems = []; + const sourceLocaleEntry = locales.get(sourceLocale); + if (!sourceLocaleEntry) { + throw new Error(`Missing source locale: ${sourceLocale}.json`); + } + + const sourceFlattened = flattenObject(sourceLocaleEntry.data); + const sourceKeys = Object.keys(sourceFlattened).sort(); + const referencedKeys = getReferencedTranslationKeys(); + const missingReferencedKeys = referencedKeys.filter((key) => !(key in sourceFlattened)); + + if (missingReferencedKeys.length > 0) { + problems.push( + [ + `Missing keys in ${sourceLocale}.json referenced by source files:`, + ...missingReferencedKeys.map((key) => ` - ${key}`), + ].join('\n') + ); + } + + for (const [localeName, localeEntry] of locales.entries()) { + if (localeName === sourceLocale) { + continue; + } + + const targetFlattened = flattenObject(localeEntry.data); + const targetKeys = Object.keys(targetFlattened).sort(); + const { missing, extra } = compareKeys(sourceKeys, targetKeys); + const expectedStructure = buildSyncedLocale(sourceLocaleEntry.data, localeEntry.data); + const expectedJson = `${JSON.stringify(expectedStructure, null, 2)}\n`; + const actualJson = fs.readFileSync(localeEntry.filePath, 'utf8'); + + if (missing.length > 0 || extra.length > 0) { + const lines = [`Locale ${localeName}.json is out of sync with ${sourceLocale}.json:`]; + if (missing.length > 0) { + lines.push(...missing.map((key) => ` - missing: ${key}`)); + } + if (extra.length > 0) { + lines.push(...extra.map((key) => ` - extra: ${key}`)); + } + problems.push(lines.join('\n')); + } + + if (actualJson !== expectedJson) { + problems.push( + `Locale ${localeName}.json key order/structure does not match ${sourceLocale}.json. Run \`npm run i18n:sync\`.` + ); + } + } + + return problems; +} + +function runCheck() { + const locales = getLocales(); + const problems = collectCheckProblems(locales); + + if (problems.length > 0) { + console.error(problems.join('\n\n')); + process.exitCode = 1; + return; + } + + console.log('i18n check passed.'); +} + +function runSync() { + const locales = getLocales(); + const sourceLocaleEntry = locales.get(sourceLocale); + if (!sourceLocaleEntry) { + throw new Error(`Missing source locale: ${sourceLocale}.json`); + } + + for (const [localeName, localeEntry] of locales.entries()) { + if (localeName === sourceLocale) { + continue; + } + + const synced = buildSyncedLocale(sourceLocaleEntry.data, localeEntry.data); + writeJson(localeEntry.filePath, synced); + } + + console.log(`Synchronized ${locales.size - 1} locale file(s) to match ${sourceLocale}.json.`); +} + +const command = process.argv[2] ?? 'check'; + +if (command === 'check') { + runCheck(); +} else if (command === 'sync') { + runSync(); +} else { + console.error(`Unknown command: ${command}`); + console.error('Usage: node scripts/i18n.mjs [check|sync]'); + process.exitCode = 1; +} diff --git a/src/app.html b/src/app.html index 7226faa..2e8f7d5 100644 --- a/src/app.html +++ b/src/app.html @@ -1,14 +1,80 @@ - + - + + + %sveltekit.head%
%sveltekit.body% @@ -28,4 +94,4 @@ .overlap-children > * { grid-area: 1/1; } - \ No newline at end of file + diff --git a/src/app.postcss b/src/app.postcss index d6bb6e4..d905e72 100644 --- a/src/app.postcss +++ b/src/app.postcss @@ -11,7 +11,7 @@ body { */ html, body { - @apply overflow-y-scroll; + @apply h-full overflow-hidden; } /* modern theme */ diff --git a/src/lib/Navigation.svelte b/src/lib/Navigation.svelte index 772d1de..71f80aa 100644 --- a/src/lib/Navigation.svelte +++ b/src/lib/Navigation.svelte @@ -9,11 +9,13 @@ import RawMdiRouter from '~icons/mdi/router'; import RawMdiSecurity from '~icons/mdi/security'; import RawMdiSettings from '~icons/mdi/settings'; + import RawMdiChartLine from '~icons/mdi/chart-line'; // import { ApiKeyInfoStore, ApiKeyStore, hasValidApi } from './Stores'; import { onMount, type Component } from 'svelte'; import { page } from '$app/state'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; type NavigationProps = { labels?: boolean @@ -26,7 +28,7 @@ const DrawerStore = getDrawerStore(); function classesActive(href: string): string { - return href === page.route.id ? 'bg-primary-300 dark:bg-primary-700' : ''; + return href === page.route.id ? 'variant-filled-primary' : ''; } let newPath = $state(''); @@ -37,18 +39,18 @@ type Page = { path: string; - name: string; + nameKey: string; logo: Component; }; const allPages: Page[] = [ - { path: '/', name: 'Home', logo: RawMdiHome }, - { path: '/users', name: 'Users', logo: RawMdiPerson }, - { path: '/nodes', name: 'Nodes', logo: RawMdiDevices }, - { path: '/deploy', name: 'Deploy', logo: RawMdiHomeGroupPlus }, - { path: '/routes', name: 'Routes', logo: RawMdiRouter }, - { path: '/acls', name: 'ACLs', logo: RawMdiSecurity }, - { path: '/settings', name: 'Settings', logo: RawMdiSettings }, + { path: '/', nameKey: 'navigation.home', logo: RawMdiHome }, + { path: '/users', nameKey: 'navigation.users', logo: RawMdiPerson }, + { path: '/nodes', nameKey: 'navigation.nodes', logo: RawMdiDevices }, + { path: '/deploy', nameKey: 'navigation.deploy', logo: RawMdiHomeGroupPlus }, + { path: '/routes', nameKey: 'navigation.routes', logo: RawMdiRouter }, + { path: '/acls', nameKey: 'navigation.acls', logo: RawMdiSecurity }, + { path: '/settings', nameKey: 'navigation.settings', logo: RawMdiSettings }, ].filter((p) => p != undefined); const pages = $derived.by(() => App.hasValidApi ? allPages : allPages.slice(-1)); @@ -70,7 +72,7 @@ {#if labels} - {p.name} + {$_(p.nameKey)} {/if} diff --git a/src/lib/States.svelte.ts b/src/lib/States.svelte.ts index 022847e..6e357fa 100644 --- a/src/lib/States.svelte.ts +++ b/src/lib/States.svelte.ts @@ -5,8 +5,13 @@ import type { User, Node, PreAuthKey, ApiKeyInfo, ApiApiKeys, Deployment } from import { getUsers, getPreAuthKeys, getNodes } from '$lib/common/api/get'; import type { ToastStore } from '@skeletonlabs/skeleton'; import { apiGet } from './common/api'; +import { setPolicy } from '$lib/common/api/modify'; +import type { ACLBuilder } from '$lib/common/acl.svelte'; import { arraysEqual, clone, toastError, toastWarning } from './common/funcs'; import { debug } from './common/debug'; +import { _ } from 'svelte-i18n'; +import { get } from 'svelte/store'; +import { getInitialLocale, persistLocalePreference, type SupportedLocale } from '$lib/i18n'; export type LayoutStyle = 'tile' | 'list'; @@ -40,12 +45,12 @@ export class State { } -// state that is wrapped in LocalStorage +// state that is wrapped in LocalStorage or SessionStorage export class StateLocal { #key: string; #value = $state() as T; #effect?: (value?: T) => void; - // #saver = $derived(this.save(this.#value)) + #session: boolean; get key() { return this.#key; @@ -57,33 +62,50 @@ export class StateLocal { set value(value: T) { this.#value = value; - // this.save(this.#value); if(this.#effect !== undefined) { this.#effect(value); } } + get storage(): Storage | null { + if (!browser) return null; + return this.#session ? sessionStorage : localStorage; + } + save(value: T) { - debug(`Saving '${this.#key}' in localStorage...`); - localStorage.setItem(this.#key, this.serialize(value)); + debug(`Saving '${this.#key}' in ${this.#session ? 'sessionStorage' : 'localStorage'}...`); + this.storage?.setItem(this.#key, this.serialize(value)); } - constructor(key: string, valueDefault: T, effect?: (value?: T) => void) { + constructor( + key: string, + valueDefault: T, + effect?: (value?: T) => void, + session: boolean = false, + saveDefaultOnInit: boolean = true, + ) { this.#key = key; this.#effect = effect; + this.#value = valueDefault; + this.#session = session; if(browser){ - const storedValue = localStorage.getItem(this.#key); + const storedValue = this.storage?.getItem(this.#key); + const hasStoredValue = storedValue !== null; if (storedValue) { this.#value = this.deserialize(storedValue); - } else { - this.#value = valueDefault; } - - // how do I clean this up? + + let initialSaveSkipped = false; $effect.root(()=>{ $effect(()=>{ + if (!saveDefaultOnInit && !hasStoredValue && !initialSaveSkipped) { + initialSaveSkipped = true; + return; + } + + initialSaveSkipped = true; this.save(this.#value); }) }) @@ -95,7 +117,16 @@ export class StateLocal { } deserialize(item: string): T { - return JSON.parse(item); + try { + return JSON.parse(item) as T; + } catch (error) { + if (typeof this.#value === 'string') { + return item as T; + } + + debug(`Failed to deserialize '${this.#key}', falling back to default value.`, error); + return this.#value; + } } } @@ -116,10 +147,40 @@ export class HeadscaleAdmin { } }) + // language settings + language = new StateLocal( + 'locale', + getInitialLocale(), + (language) => { + if (language !== undefined) { + persistLocalePreference(language); + } + }, + false, + false, + ) + // api info apiValid = $state(false); apiUrl = new StateLocal('apiUrl', ''); - apiKey = new StateLocal('apiKey', ''); + + #apiKey = new StateLocal('apiKey', ''); + #apiKeySession = new StateLocal('apiKey', '', undefined, true); + + get apiKey(): StateLocal { + const key = this.apiRememberMe.value ? this.#apiKey : this.#apiKeySession; + // If we switched from remember to not remember, or vice versa, ensure the key is transferred + if (this.apiRememberMe.value && !this.#apiKey.value && this.#apiKeySession.value) { + this.#apiKey.value = this.#apiKeySession.value; + this.#apiKeySession.value = ''; + } else if (!this.apiRememberMe.value && !this.#apiKeySession.value && this.#apiKey.value) { + this.#apiKeySession.value = this.#apiKey.value; + this.#apiKey.value = ''; + } + return key; + } + + apiRememberMe = new StateLocal('apiRememberMe', false); apiTtl = new StateLocal('apiTTL', 10000); apiKeyInfo = new StateLocal('apiKeyInfo', { authorized: null, @@ -127,8 +188,8 @@ export class HeadscaleAdmin { informedUnauthorized: false, informedExpiringSoon: false, }) - hasApiKey = $derived(isInitialized() && !!this.apiKey.value) - hasApiUrl = $derived(isInitialized() && !!this.apiUrl.value) + hasApiKey = $derived(isInitialized() && !!this.apiKey.value) + hasApiUrl = $derived(isInitialized() && !!this.apiUrl.value) hasApi = $derived(this.hasApiKey && this.hasApiUrl) hasValidApi = $derived(this.hasApi && this.apiKeyInfo.value.authorized === true) @@ -212,6 +273,28 @@ export class HeadscaleAdmin { if (preAuthKeys === undefined) { preAuthKeys = await getPreAuthKeys() } + + // Keep full keys (no asterisks) for a given ID if the new one is masked + // This preserves the initially shown full key when API refreshes show masked version + preAuthKeys = preAuthKeys.map((newKey) => { + const existingKey = this.preAuthKeys.value.find(k => k.id === newKey.id); + + // Safety checks for key field + if (existingKey && + newKey.key && existingKey.key && + typeof newKey.key === 'string' && + typeof existingKey.key === 'string') { + + // If new key is masked (has asterisks) and existing is not, keep the full key + if (newKey.key.includes('*') && !existingKey.key.includes('*')) { + debug('Preserving full key for ID', newKey.id, '- old:', existingKey.key.substring(0, 20), 'new:', newKey.key.substring(0, 20)); + return existingKey; + } + } + + return newKey; + }); + if(!arraysEqual(this.preAuthKeys.value, preAuthKeys)){ this.preAuthKeys.value = [...preAuthKeys] return true @@ -221,25 +304,46 @@ export class HeadscaleAdmin { async populateApiKeyInfo(): Promise { const { apiKeys } = await apiGet(`/api/v1/apikey`); - const myKey = apiKeys.filter((key) => this.apiKey.value.startsWith(key.prefix))[0]; + const myKey = apiKeys.find((key) => { + const cleanPrefix = key.prefix.replace(/\*+$/, ''); + return this.apiKey.value.startsWith(cleanPrefix); + }); + const apiKeyInfo = this.apiKeyInfo.value - apiKeyInfo.expires = myKey.expiration; apiKeyInfo.authorized = true; + if (myKey) { + apiKeyInfo.expires = myKey.expiration; + } + this.apiKeyInfo.value = {...apiKeyInfo}; return true; } async populateAll(handler?: (err: unknown) => void, repeat: boolean = true){ - if (this.hasValidApi) { - const promises = [] - promises.push(this.populateUsers()); - promises.push(this.populateNodes()); - promises.push(this.populatePreAuthKeys()); - // promises.push(this.populateRoutes()); - promises.push(this.populateApiKeyInfo()); - await Promise.allSettled(promises); - promises.forEach((p) => p.catch(handler)); - debug('Completed all store population requests.'); + if (this.hasApi) { + try { + await this.populateApiKeyInfo(); + } catch (err) { + handler?.(err); + } + + if (this.hasValidApi) { + const results = await Promise.allSettled([ + this.populateUsers(), + this.populateNodes(), + this.populatePreAuthKeys(), + // this.populateRoutes(), + this.populateApiKeyInfo(), + ]); + + results.forEach((result) => { + if (result.status === 'rejected') { + handler?.(result.reason); + } + }); + + debug('Completed all store population requests.'); + } } if (repeat === true) { @@ -249,6 +353,10 @@ export class HeadscaleAdmin { } } + async setPolicy(acl: ACLBuilder) { + await setPolicy(acl); + } + toggleLayout(layout?: Valued) { if (layout) { layout.value = (layout.value === 'tile' ? 'list' : 'tile'); @@ -267,7 +375,7 @@ export class HeadscaleAdmin { } } -export const App = $state(new HeadscaleAdmin()) +export const App = new HeadscaleAdmin() function isInitialized(): boolean { @@ -293,7 +401,7 @@ export function informUserUnauthorized(toastStore: ToastStore) { } App.apiKeyInfo.value.informedUnauthorized = true; App.apiKeyInfo.value.authorized = false; - toastError('API Key is Unauthorized or Invalid', toastStore); + toastError(get(_)( 'settings.unauthorizedMessage' ), toastStore); }); } @@ -302,8 +410,7 @@ export function informUserExpiringSoon(toastStore: ToastStore) { if (App.apiKeyInfo.value.informedExpiringSoon === true) { return; } - App.apiKeyInfo.value.informedUnauthorized = true; - App.apiKeyInfo.value.authorized = false; - toastWarning('API Key Expires Soon', toastStore); + App.apiKeyInfo.value.informedExpiringSoon = true; + toastWarning(get(_)( 'settings.expiringSoonMessage' ), toastStore); }); -} \ No newline at end of file +} diff --git a/src/lib/cards/CardListContainer.svelte b/src/lib/cards/CardListContainer.svelte index 2d87118..a3d8c84 100644 --- a/src/lib/cards/CardListContainer.svelte +++ b/src/lib/cards/CardListContainer.svelte @@ -2,6 +2,6 @@ let { children } = $props() -
+
{@render children()}
diff --git a/src/lib/cards/CardListItem.svelte b/src/lib/cards/CardListItem.svelte index 042104e..6924cae 100644 --- a/src/lib/cards/CardListItem.svelte +++ b/src/lib/cards/CardListItem.svelte @@ -13,7 +13,7 @@ diff --git a/src/lib/cards/CardListPage.svelte b/src/lib/cards/CardListPage.svelte index ac93317..06dc6ca 100644 --- a/src/lib/cards/CardListPage.svelte +++ b/src/lib/cards/CardListPage.svelte @@ -7,7 +7,7 @@ let { children }: CardListPageProps = $props() -
+
{@render children()} diff --git a/src/lib/cards/CardTileContainer.svelte b/src/lib/cards/CardTileContainer.svelte index fbcd783..28dfdc8 100644 --- a/src/lib/cards/CardTileContainer.svelte +++ b/src/lib/cards/CardTileContainer.svelte @@ -4,24 +4,36 @@ type CardTileContainerProps = { classes?: string, - onclick?: MouseEventHandler, + onclick?: MouseEventHandler, + href?: string, children: Snippet, } let { classes = '', onclick = undefined, + href = undefined, children, }: CardTileContainerProps = $props() const classesFinal = $derived( - 'col-span-12 xs:col-span-12 sm:col-span-6 md:col-span-6 lg:col-span-6 xl:col-span-4 2xl:col-span-3 card ' + - (onclick === undefined ? '' : 'card-hover ') + + 'col-span-12 xs:col-span-12 sm:col-span-6 md:col-span-6 lg:col-span-6 xl:col-span-4 2xl:col-span-3 card transition-all duration-200 ' + + (onclick === undefined && href === undefined ? '' : 'card-hover cursor-pointer ') + classes ); -
- +
+ {#if href} + + {@render children()} + + {:else if onclick} + + {:else} +
+ {@render children()} +
+ {/if}
\ No newline at end of file diff --git a/src/lib/cards/CardTilePage.svelte b/src/lib/cards/CardTilePage.svelte index 1055892..62750fa 100644 --- a/src/lib/cards/CardTilePage.svelte +++ b/src/lib/cards/CardTilePage.svelte @@ -6,7 +6,7 @@ } let { children }: CardTitlePageProps = $props() -
+
{@render children()}
diff --git a/src/lib/cards/acl/GroupListCard.svelte b/src/lib/cards/acl/GroupListCard.svelte index c449b04..496ce70 100644 --- a/src/lib/cards/acl/GroupListCard.svelte +++ b/src/lib/cards/acl/GroupListCard.svelte @@ -6,11 +6,12 @@ import Delete from '$lib/parts/Delete.svelte'; import MultiSelect from '$lib/parts/MultiSelect.svelte'; import Text from '$lib/parts/Text.svelte'; + import { _ } from 'svelte-i18n'; import { App } from '$lib/States.svelte'; import { debug } from '$lib/common/debug'; import { getToastStore } from '@skeletonlabs/skeleton'; - import { toastSuccess, toastError } from '$lib/common/funcs'; + import { toastSuccess, toastError, getUserAclName } from '$lib/common/funcs'; import RawMdiGroup from '~icons/mdi/account-group-outline'; @@ -25,9 +26,7 @@ let {acl = $bindable(), groupName, open = $bindable()}: GroupListCardProps = $props() const groupMembers = $derived(acl.getGroupMembers(groupName)); - const userNames = $derived(App.users.value.map((u) => { - return u.email ? u.email : u.name; - }).toSorted()) + const userNames = $derived(App.users.value.map(getUserAclName).toSorted()) let group = $state(makeGroup()); let groupNameNew = $state(''); @@ -47,7 +46,7 @@ try { if (groupName !== groupNameNew) { acl.renameGroup(groupName, groupNameNew); - toastSuccess(`Group renamed from '${groupName}' to '${groupNameNew}'`, ToastStore); + toastSuccess($_('cards.groupRenamedSuccess', { values: { oldName: groupName, newName: groupNameNew } }), ToastStore); groupName = groupNameNew; } return true; @@ -63,7 +62,7 @@ deleting = true; try { acl.deleteGroup(groupName); - toastSuccess(`Group '${groupName}' deleted`, ToastStore); + toastSuccess($_('cards.groupDeleted', { values: { name: groupName } }), ToastStore); } catch (e) { if (e instanceof Error) { toastError('', ToastStore, e); @@ -97,7 +96,7 @@ {#snippet children()}

- Members of + {$_('cards.membersOf')}
diff --git a/src/lib/cards/acl/HostListCard.svelte b/src/lib/cards/acl/HostListCard.svelte index 71b1e5c..17875e8 100644 --- a/src/lib/cards/acl/HostListCard.svelte +++ b/src/lib/cards/acl/HostListCard.svelte @@ -6,6 +6,7 @@ import Delete from '$lib/parts/Delete.svelte'; import { debug } from '$lib/common/debug'; import Text from '$lib/parts/Text.svelte'; + import { _ } from 'svelte-i18n'; const ToastStore = getToastStore(); @@ -74,7 +75,7 @@ function deleteHost() { try { acl.deleteHost(host.name); - toastSuccess(`Host '${host.name}' deleted`, ToastStore); + toastSuccess($_('cards.hostDeleted', { values: { name: host.name } }), ToastStore); } catch (e) { debug(e); if (e instanceof Error) { @@ -108,12 +109,12 @@ class="card p-4 variant-filled-warning text-center {popupShow ? '' : 'invisible'}" data-popup="popupHover-host-{hostName}" > -

Host '{hostName}' has the same name as a user.
Please rename the host.

+

{$_('cards.hostRenameWarning', { values: { hostName } })}

{#if userNames.includes(hostName)} diff --git a/src/lib/cards/acl/ListEntry.svelte b/src/lib/cards/acl/ListEntry.svelte index 45762ef..a5f9813 100644 --- a/src/lib/cards/acl/ListEntry.svelte +++ b/src/lib/cards/acl/ListEntry.svelte @@ -27,7 +27,7 @@ diff --git a/src/lib/cards/acl/PolicyListCard.svelte b/src/lib/cards/acl/PolicyListCard.svelte index 82d313b..b59526a 100644 --- a/src/lib/cards/acl/PolicyListCard.svelte +++ b/src/lib/cards/acl/PolicyListCard.svelte @@ -1,10 +1,11 @@ - + {#snippet children()}

- Sources: + {$_('cards.sources')}

{#each rule.src as src, i}
{src} @@ -204,7 +218,7 @@ {/each}

- Destinations: + {$_('cards.destinations')}

{#each rule.dst as dst, i}
{dst} @@ -269,7 +283,7 @@
{/each}

- Usernames: + {$_('cards.usernames')}

{ - const us = App.users.value.map(u => u.name) + const us = App.users.value.map(getUserAclName) us.sort() const gs = acl.getGroupNames(true) @@ -57,7 +58,7 @@ try { if (tag.name !== tagNameNew) { acl.renameTag(tag.name, tagNameNew); - toastSuccess(`Tag renamed from '${tag.name}' to '${tagNameNew}'`, ToastStore); + toastSuccess($_('cards.tagRenamedSuccess', { values: { oldName: tag.name, newName: tagNameNew } }), ToastStore); tagName = tagNameNew; } return true; @@ -76,7 +77,7 @@ loading = true try{ acl.deleteTag(tag.name); - toastSuccess(`Tag '${tag.name}' deleted`, ToastStore) + toastSuccess($_('cards.tagDeleted', { values: { name: tag.name } }), ToastStore) }catch(e){ if(e instanceof Error){ toastError('', ToastStore, e); @@ -101,7 +102,7 @@ {#snippet children()}

- Owners of + {$_('cards.ownersOf')}
diff --git a/src/lib/cards/common/ItemCreatedAt.svelte b/src/lib/cards/common/ItemCreatedAt.svelte index 3a0b36a..9c5a837 100644 --- a/src/lib/cards/common/ItemCreatedAt.svelte +++ b/src/lib/cards/common/ItemCreatedAt.svelte @@ -1,6 +1,8 @@ - - {new Date(item.createdAt).toLocaleString('en-Gb', { - minute: '2-digit', - year: 'numeric', - month: 'short', - day: '2-digit', - hour: '2-digit', - hour12: false, - })} + + {dateToStr(item.createdAt)} diff --git a/src/lib/cards/common/ItemDelete.svelte b/src/lib/cards/common/ItemDelete.svelte index d04f1f0..9ddb826 100644 --- a/src/lib/cards/common/ItemDelete.svelte +++ b/src/lib/cards/common/ItemDelete.svelte @@ -9,6 +9,7 @@ import { toastError, toastSuccess } from '$lib/common/funcs'; import Delete from '$lib/parts/Delete.svelte'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; type ItemDeleteProps = { item: Named, @@ -33,27 +34,27 @@ if (isUser(item)) { if (await deleteUser(item)) { - toastSuccess(`Deleted User "${name}" (ID: ${id})`, ToastStore); + toastSuccess($_('cards.deletedUser', { values: { name, id } }), ToastStore); DrawerStore.close() } else { - let msg = `Failed to Delete User "${name}" (${id}).`; + let msg = $_('cards.failedDeleteUser', { values: { name, id } }); if(App.nodes.value.some((node) => node.user.id === item.id)){ - msg += " Still has nodes." + msg += $_('cards.stillHasNodes'); } toastError(msg, ToastStore); } } if (isNode(item)) { if (await deleteNode(item)) { - toastSuccess(`Deleted machine "${name}" (${id})`, ToastStore); + toastSuccess($_('cards.deletedMachine', { values: { name, id } }), ToastStore); DrawerStore.close() } else { - toastError(`Failed to Delete Nachine "${name}" (${id})`, ToastStore); + toastError($_('cards.failedDeleteMachine', { values: { name, id } }), ToastStore); } } } - + diff --git a/src/lib/cards/common/ItemListName.svelte b/src/lib/cards/common/ItemListName.svelte index cd4b51e..0a0f561 100644 --- a/src/lib/cards/common/ItemListName.svelte +++ b/src/lib/cards/common/ItemListName.svelte @@ -6,6 +6,7 @@ import RawMdiRename from '~icons/mdi/rename'; import RawMdiCheckCircleOutline from '~icons/mdi/check-circle-outline'; import RawMdiCloseCircleOutline from '~icons/mdi/close-circle-outline'; + import { _ } from 'svelte-i18n'; import { renameNode, renameUser } from '$lib/common/api'; import { toastError, focus } from '$lib/common/funcs'; import { getToastStore } from '@skeletonlabs/skeleton'; @@ -32,7 +33,7 @@ const ToastStore = getToastStore(); - +
{#if showRename}
- {#each App.users.value as user} - + {/each} + + {:else} + + {diff.message} + + + + { + loading = true + try{ + App.updateValue(App.nodes, await expireNode(node)) + } finally { + loading = false + } + }} + /> + + {/if}
- + \ No newline at end of file diff --git a/src/lib/cards/node/NodeHostname.svelte b/src/lib/cards/node/NodeHostname.svelte index 81d03f2..fb0de63 100644 --- a/src/lib/cards/node/NodeHostname.svelte +++ b/src/lib/cards/node/NodeHostname.svelte @@ -1,6 +1,7 @@ - + {node.name} diff --git a/src/lib/cards/node/NodeInfo.svelte b/src/lib/cards/node/NodeInfo.svelte index b3924bb..8798c0d 100644 --- a/src/lib/cards/node/NodeInfo.svelte +++ b/src/lib/cards/node/NodeInfo.svelte @@ -38,8 +38,10 @@ - - + {#if node.availableRoutes.length > 0} + + + {/if} diff --git a/src/lib/cards/node/NodeLastSeen.svelte b/src/lib/cards/node/NodeLastSeen.svelte index 8bc9e85..0b45f4f 100644 --- a/src/lib/cards/node/NodeLastSeen.svelte +++ b/src/lib/cards/node/NodeLastSeen.svelte @@ -3,6 +3,7 @@ import type { Node } from '$lib/common/types'; import { onMount } from 'svelte'; import CardListEntry from '../CardListEntry.svelte'; + import { _ } from 'svelte-i18n'; type NodeLastSeenProps = { node: Node, @@ -21,9 +22,9 @@ }); - + {#if node.online} - Online Now + {$_('cards.onlineNow')} {:else} {lastSeen} {/if} diff --git a/src/lib/cards/node/NodeListCard.svelte b/src/lib/cards/node/NodeListCard.svelte index 45e505c..8206d77 100644 --- a/src/lib/cards/node/NodeListCard.svelte +++ b/src/lib/cards/node/NodeListCard.svelte @@ -6,29 +6,52 @@ import CardListEntry from '../CardListEntry.svelte'; import NodeInfo from './NodeInfo.svelte'; import OnlineNodeIndicator from '$lib/parts/OnlineNodeIndicator.svelte'; + import { _ } from 'svelte-i18n'; type NodeListCardProps = { node: Node, open?: boolean, + selectable?: boolean, + selected?: boolean, + onToggleSelect?: (nodeId: string) => void, } - let { node = $bindable(), open = $bindable(false) }: NodeListCardProps = $props() + let { + node = $bindable(), + open = $bindable(false), + selectable = false, + selected = false, + onToggleSelect = () => {}, + }: NodeListCardProps = $props() + + function handleCheckboxClick(event: Event) { + event.stopPropagation(); + onToggleSelect(node.id); + } + {#if selectable} + + {/if}
- + {node.givenName}
diff --git a/src/lib/cards/node/NodeOwner.svelte b/src/lib/cards/node/NodeOwner.svelte index 3c7625b..90e66fb 100644 --- a/src/lib/cards/node/NodeOwner.svelte +++ b/src/lib/cards/node/NodeOwner.svelte @@ -2,17 +2,9 @@ import CardListEntry from '../CardListEntry.svelte'; import type { Node } from '$lib/common/types'; import OnlineUserIndicator from '$lib/parts/OnlineUserIndicator.svelte'; - import { changeNodeOwner } from '$lib/common/api'; - import { openDrawer, toastError, toastSuccess } from '$lib/common/funcs'; - import { debug } from '$lib/common/debug'; - import { getDrawerStore, getToastStore } from '@skeletonlabs/skeleton'; - import { slide } from 'svelte/transition'; - - import RawMdiSwapHorizontal from '~icons/mdi/swap-horizontal'; - import RawMdiCheckCircleOutline from '~icons/mdi/check-circle-outline'; - import RawMdiCloseCircleOutline from '~icons/mdi/close-circle-outline'; - - import { App } from '$lib/States.svelte'; + import { openDrawer } from '$lib/common/funcs'; + import { getDrawerStore } from '@skeletonlabs/skeleton'; + import { _ } from 'svelte-i18n'; type NodeOwnerProps = { node: Node, @@ -20,17 +12,11 @@ let { node }: NodeOwnerProps = $props() const drawerStore = getDrawerStore(); - let transferUser = $state(''); - let showTransfer = $state(false); - let transferring = $state(false); - - const ToastStore = getToastStore(); - +
- { @@ -39,65 +25,6 @@ > {node.user.name} - -
- {#if showTransfer} -
- New Owner: - - - -
- {/if}
diff --git a/src/lib/cards/node/NodeRegistrationMethod.svelte b/src/lib/cards/node/NodeRegistrationMethod.svelte index fad99ed..14b67c9 100644 --- a/src/lib/cards/node/NodeRegistrationMethod.svelte +++ b/src/lib/cards/node/NodeRegistrationMethod.svelte @@ -1,6 +1,7 @@ - + {nodeRegMethod} diff --git a/src/lib/cards/node/NodeRoutes.svelte b/src/lib/cards/node/NodeRoutes.svelte index 860462c..47e6372 100644 --- a/src/lib/cards/node/NodeRoutes.svelte +++ b/src/lib/cards/node/NodeRoutes.svelte @@ -3,6 +3,7 @@ import type { Node } from '$lib/common/types'; import { debug } from '$lib/common/debug' import NodeRoute from './NodeRoute.svelte'; + import { _ } from 'svelte-i18n'; import ToggleOff from '~icons/mdi/toggle-switch-variant-off'; import ToggleOn from '~icons/mdi/toggle-switch-variant'; import { disableRoutes, enableRoutes } from '$lib/common/api'; @@ -25,41 +26,45 @@ - -
- - -
+ + {#if node.availableRoutes.length > 0} +
+ + +
+ {/if} {#if childBottom === undefined} {#each node.availableRoutes as route}
diff --git a/src/lib/cards/node/NodeTags.svelte b/src/lib/cards/node/NodeTags.svelte index 534f41d..ec23a95 100644 --- a/src/lib/cards/node/NodeTags.svelte +++ b/src/lib/cards/node/NodeTags.svelte @@ -1,14 +1,18 @@ -
-

The following tags have been prevented by the current ACL:

-

- {#if popupInvalidTagsShow == true} - {#each tagsInvalid as tag} - - {/each} - {/if} -

-
-
-
- + - - {#snippet childTitle()} - - Advertised Tags: - {#if tagsInvalid.length > 0} - - {/if} - - {/snippet} -
- {#each tagsValid as tag} - - {/each} -
-
diff --git a/src/lib/cards/node/NodeTileCard.svelte b/src/lib/cards/node/NodeTileCard.svelte index 5214bff..512d4b2 100644 --- a/src/lib/cards/node/NodeTileCard.svelte +++ b/src/lib/cards/node/NodeTileCard.svelte @@ -14,16 +14,30 @@ import OnlineNodeIndicator from '$lib/parts/OnlineNodeIndicator.svelte'; import OnlineUserIndicator from '$lib/parts/OnlineUserIndicator.svelte'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; type NodeTileCardProps = { node: Node, + selectable?: boolean, + selected?: boolean, + onToggleSelect?: (nodeId: string) => void, } - let { node = $bindable() }: NodeTileCardProps = $props() + let { + node = $bindable(), + selectable = false, + selected = false, + onToggleSelect = () => {}, + }: NodeTileCardProps = $props() let lastSeen = $state(getTimeDifferenceMessage(getTime(node.lastSeen))); const routeCount = $derived(node.availableRoutes.length); const drawerStore = getDrawerStore(); + + function handleCheckboxClick(event: Event) { + event.stopPropagation(); + onToggleSelect(node.id); + } let color = $derived( (xxHash32(node.id + ':' + node.givenName, 0xbeefbabe) & 0xff_ff_ff) @@ -42,39 +56,60 @@ }); - openDrawer(drawerStore, 'nodeDrawer-' + node.id, node)}> + openDrawer(drawerStore, 'nodeDrawer-' + node.id, node)} classes={selected ? 'ring-2 ring-primary-500' : ''}> + {#if selectable} +
+ +
+ {/if}
- ID: {node.id} + {$_('common.id')}: {node.id}
{node.givenName}
- + {dateToStr(node.createdAt)} - + {#if node.online} - Online Now + {$_('cards.onlineNow')} {:else} {lastSeen} {/if} - +
{node.user.name}
- +
{node.ipAddresses.filter((s) => /^\d+\.\d+\.\d+\.\d+$/.test(s)).at(0)}
- + {routeCount} + +
+ {#if node.tags.length > 0} + {#each node.tags as tag} + {tag.replace('tag:', '')} + {/each} + {:else} + - + {/if} +
+

diff --git a/src/lib/cards/route/RouteListCard.svelte b/src/lib/cards/route/RouteListCard.svelte index 538e767..309ada7 100644 --- a/src/lib/cards/route/RouteListCard.svelte +++ b/src/lib/cards/route/RouteListCard.svelte @@ -6,6 +6,7 @@ import CardListEntry from '../CardListEntry.svelte'; import RouteInfo from './RouteInfo.svelte'; import OnlineNodeIndicator from '$lib/parts/OnlineNodeIndicator.svelte'; + import { _ } from 'svelte-i18n'; type RouteListCardProps = { node: Node, @@ -18,7 +19,7 @@ @@ -27,7 +28,7 @@
- + {node.givenName}
diff --git a/src/lib/cards/route/RouteTileCard.svelte b/src/lib/cards/route/RouteTileCard.svelte index ed8807a..9764db0 100644 --- a/src/lib/cards/route/RouteTileCard.svelte +++ b/src/lib/cards/route/RouteTileCard.svelte @@ -8,6 +8,7 @@ import CardTileContainer from '../CardTileContainer.svelte'; import CardTileEntry from '../CardTileEntry.svelte'; import OnlineNodeIndicator from '$lib/parts/OnlineNodeIndicator.svelte'; + import { _ } from 'svelte-i18n'; import RouteInfo from './RouteInfo.svelte'; type RouteTileCardProps = { @@ -33,7 +34,7 @@
- ID: {node.id} + {$_('common.id')}: {node.id}
{node.givenName} diff --git a/src/lib/cards/user/UserCreate.svelte b/src/lib/cards/user/UserCreate.svelte index bba8675..17553ea 100644 --- a/src/lib/cards/user/UserCreate.svelte +++ b/src/lib/cards/user/UserCreate.svelte @@ -4,6 +4,7 @@ import { App } from '$lib/States.svelte'; import { getToastStore } from '@skeletonlabs/skeleton'; import RawMdiCheckCircleOutline from '~icons/mdi/check-circle-outline'; + import { _ } from 'svelte-i18n'; type UserCreateProps = { show: boolean, @@ -22,12 +23,12 @@ try { const u = await createUser(username); App.users.value.push(u) - toastSuccess('Created user "' + username + '"', toastStore); + toastSuccess($_('common.createdUser') + ' "' + username + '"', toastStore); show = false; username = ''; } catch (error) { if (error instanceof Error) { - toastError('Failed to create user "' + username + '"', toastStore, error); + toastError($_('common.failedCreateUser') + ' "' + username + '"', toastStore, error); } } finally { loading = false; @@ -38,9 +39,11 @@
import type { User } from '$lib/common/types'; import CardListEntry from '../CardListEntry.svelte'; + import { _ } from 'svelte-i18n'; type ItemCreatedAtProps = { user: User, @@ -10,6 +11,6 @@ - + {user.displayName} \ No newline at end of file diff --git a/src/lib/cards/user/UserEmail.svelte b/src/lib/cards/user/UserEmail.svelte index 98833e5..0e7bf65 100644 --- a/src/lib/cards/user/UserEmail.svelte +++ b/src/lib/cards/user/UserEmail.svelte @@ -1,6 +1,7 @@ - + {user.email} \ No newline at end of file diff --git a/src/lib/cards/user/UserListCard.svelte b/src/lib/cards/user/UserListCard.svelte index cfb78ca..a15e8a8 100644 --- a/src/lib/cards/user/UserListCard.svelte +++ b/src/lib/cards/user/UserListCard.svelte @@ -6,6 +6,7 @@ import CardListEntry from '../CardListEntry.svelte'; import UserInfo from './UserInfo.svelte'; import OnlineUserIndicator from '$lib/parts/OnlineUserIndicator.svelte'; + import { _ } from 'svelte-i18n'; type UserListCardProps = { user: User, @@ -17,7 +18,7 @@ @@ -26,7 +27,7 @@
- + {getUserDisplay(user)} diff --git a/src/lib/cards/user/UserListNodes.svelte b/src/lib/cards/user/UserListNodes.svelte index 7a180a5..4665a8d 100644 --- a/src/lib/cards/user/UserListNodes.svelte +++ b/src/lib/cards/user/UserListNodes.svelte @@ -5,6 +5,7 @@ import { openDrawer } from '$lib/common/funcs'; import { getDrawerStore } from '@skeletonlabs/skeleton'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; type UserListNodesProps = { user: User, @@ -12,17 +13,12 @@ } let { user = $bindable(), - title = 'Nodes:', + title = $_('cards.nodes'), }: UserListNodesProps = $props(); const drawerStore = getDrawerStore(); - const filteredNodes = $derived.by(() => { - if (App.users.value.filter((u) => u.id == user.id).length == 1) { - return App.nodes.value.filter((n) => n.user.id == user.id); - } - return []; - }); + const filteredNodes = $derived(App.nodes.value.filter((n) => n.user.id == user.id)); diff --git a/src/lib/cards/user/UserListPreAuthKey.svelte b/src/lib/cards/user/UserListPreAuthKey.svelte index ba15c40..081561c 100644 --- a/src/lib/cards/user/UserListPreAuthKey.svelte +++ b/src/lib/cards/user/UserListPreAuthKey.svelte @@ -4,9 +4,10 @@ import { getToastStore, popup, type PopupSettings } from '@skeletonlabs/skeleton'; import { copyToClipboard } from '$lib/common/funcs'; import Delete from '$lib/parts/Delete.svelte'; - import { expirePreAuthKey, getPreAuthKeys } from '$lib/common/api'; + import { expirePreAuthKey } from '$lib/common/api'; import { App } from '$lib/States.svelte'; import { onMount } from 'svelte'; + import { _ } from 'svelte-i18n'; type UserListPreAuthKeyProps = { preAuthKey: PreAuthKey, @@ -33,26 +34,31 @@
- - - { - await expirePreAuthKey(preAuthKey); - const keys = await getPreAuthKeys([preAuthKey.user.id]); - keys.forEach((pak) => { - App.updateValue(App.preAuthKeys, pak) - }); - }} - /> - + {#if preAuthKey.key && preAuthKey.key.length > 0} + + {:else} +
+ ⚠️ + No key available +
+ {/if}
@@ -61,14 +67,14 @@ ? 'variant-ghost-success' : 'variant-flat opacity-50'}" > - Used + {$_('cards.used')} - Expired + {$_('cards.expired')}
@@ -77,15 +83,25 @@ ? 'variant-ghost-secondary' : 'variant-flat opacity-50'}" > - Ephemeral + {$_('cards.ephemeral')} - Reusable + {$_('cards.reusable')}
+
+ + { + await expirePreAuthKey(preAuthKey); + await App.populatePreAuthKeys(); + }} + /> + +
diff --git a/src/lib/cards/user/UserListPreAuthKeys.svelte b/src/lib/cards/user/UserListPreAuthKeys.svelte index 4e1f982..5db30c9 100644 --- a/src/lib/cards/user/UserListPreAuthKeys.svelte +++ b/src/lib/cards/user/UserListPreAuthKeys.svelte @@ -8,8 +8,11 @@ import { slide } from 'svelte/transition'; import { createPreAuthKey } from '$lib/common/api'; import { debug } from '$lib/common/debug'; + import { isValidTag, toastError } from '$lib/common/funcs'; + import { InputChip, getToastStore } from '@skeletonlabs/skeleton'; import CardSeparator from '../CardSeparator.svelte'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; type UserListPreAuthKeysProps = { user: User, @@ -17,19 +20,31 @@ } let { user = $bindable(), - title = 'PreAuth Keys:', + title = $_('users.preAuthKeys') + ':', }: UserListPreAuthKeysProps = $props(); + const ToastStore = getToastStore(); let hideInvalid = $state(true); let showCreate = $state(false); let disableCreate = $state(false); let checked = $state(defaultChecked()); let expires = $state(defaultExpires()); + let tags = $state([] as string[]); const preAuthKeys = $derived( App.preAuthKeys.value.filter((p) => { - return (p.user.id === user.id) - && (!hideInvalid || (hideInvalid && !isExpiredOrUsed(p))); + // Ensure this key belongs to the current user + if (p.user.id !== user.id) { + return false; + } + + // If hideInvalid is false, show all keys + if (!hideInvalid) { + return true; + } + + // If hideInvalid is true, filter out expired or single-use keys + return !isExpiredOrUsed(p); }) ); @@ -50,7 +65,18 @@ } function isExpiredOrUsed(p: PreAuthKey): boolean { - return new Date() > new Date(p.expiration) || (p.used && !p.reusable); + // Safely check expiration - some old format keys might have issues + try { + if (!p.expiration) { + // If no expiration, consider it valid (never expires) + return p.used && !p.reusable; + } + return new Date() > new Date(p.expiration) || (p.used && !p.reusable); + } catch (e) { + debug('Error checking expiration for key', p.id, e); + // If there's an error checking expiration, don't hide the key + return false; + } }; @@ -58,7 +84,7 @@
-

Hide Invalid

+

{$_('cards.hideInvalid')}

{#if showCreate}
-
-
+ +
+ +
+ + +
+ + +
+ +
+ { + toastError($_('deploy.tagError'), ToastStore); + }} + /> +
+
+
+ + +
+ +
+ + +
+ + +
+ - -
-
- -
-
- -
diff --git a/src/lib/cards/user/UserProvider.svelte b/src/lib/cards/user/UserProvider.svelte index e18e23b..2059e45 100644 --- a/src/lib/cards/user/UserProvider.svelte +++ b/src/lib/cards/user/UserProvider.svelte @@ -1,6 +1,7 @@ - - {user.provider || 'local'} + + {user.provider || $_('cards.local')} \ No newline at end of file diff --git a/src/lib/cards/user/UserTileCard.svelte b/src/lib/cards/user/UserTileCard.svelte index 3f4b2c9..72db0c0 100644 --- a/src/lib/cards/user/UserTileCard.svelte +++ b/src/lib/cards/user/UserTileCard.svelte @@ -6,6 +6,7 @@ import CardTileContainer from '../CardTileContainer.svelte'; import OnlineUserIndicator from '$lib/parts/OnlineUserIndicator.svelte'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; type UserTileCardProps = { user: User, @@ -25,20 +26,20 @@
- ID: {user.id} + {$_('common.id')}: {user.id}
{getUserDisplay(user)}
-
Created:
+
{$_('cards.created')}
{dateToStr(new Date(user.createdAt))}
-
Nodes:
+
{$_('cards.nodes')}
{nodeCount}
diff --git a/src/lib/common/acl.svelte.ts b/src/lib/common/acl.svelte.ts index 3bb281d..69546e3 100644 --- a/src/lib/common/acl.svelte.ts +++ b/src/lib/common/acl.svelte.ts @@ -12,8 +12,8 @@ export type AclTagOwners = { [key: string]: TagOwners } export type AclHosts = { [key: string]: string } export type AclPolicies = AclPolicy[] export type AclSshRules = AclSshRule[] -export type AclPoliciesIndexed = {policy: AclPolicy, idx: number}[] -export type AclSshRulesIndexed = {rule: AclSshRule, idx: number}[] +export type AclPoliciesIndexed = { policy: AclPolicy, idx: number }[] +export type AclSshRulesIndexed = { rule: AclSshRule, idx: number }[] // metadata for ACL policy entries export type HAMeta = { @@ -72,7 +72,7 @@ export class ACLBuilder implements ACL { tagOwners = $state({}) hosts = $state({}) acls = $state([]) - ssh = $state(undefined) + ssh = $state(undefined) constructor( groups: AclGroups, @@ -112,26 +112,71 @@ export class ACLBuilder implements ACL { } static addPolicyMeta(policy: AclPolicy): boolean { - if (policy["#ha-meta"] === undefined){ - policy["#ha-meta"] = HAMetaDefault - } + if (policy["#ha-meta"] === undefined) { + policy["#ha-meta"] = HAMetaDefault + } return policy["#ha-meta"] !== undefined } static fromPolicy(acl: ACL | string): ACLBuilder { - if (typeof acl === "string"){ + if (typeof acl === "string") { return this.fromPolicy(JWCC.parse(acl)) } const ssh = acl.ssh ? [...acl.ssh] : [] - return new ACLBuilder( - {...acl.groups}, - {...acl.tagOwners}, - {...acl.hosts}, + const builder = new ACLBuilder( + { ...acl.groups }, + { ...acl.tagOwners }, + { ...acl.hosts }, [...acl.acls], [...ssh], ) + builder.normalize() + return builder + } + + // Ensures all user identifiers contain an '@' to satisfy Headscale's Go v2 parser requirements. + // This is especially important for local users like 'echo' which must be 'echo@'. + normalize() { + const hostNames = new Set(Object.keys(this.hosts)); + const isHost = (id: string) => hostNames.has(id); + + // Normalize Tag Owners + for (const tag in this.tagOwners) { + this.tagOwners[tag] = this.tagOwners[tag].map(id => ACLBuilder.normalizeIdentifier(id, false)); + } + + // Normalize ACL Policies + for (const acl of this.acls) { + acl.src = acl.src.map(id => ACLBuilder.normalizeIdentifier(id, isHost(id))); + acl.dst = acl.dst.map(dst => { + const hostPart = ACLBuilder.getPolicyDstHost(dst); + const ports = ACLBuilder.getPolicyDstPorts(dst); + if (hostPart === dst) { // No ports specified + return ACLBuilder.normalizeIdentifier(dst, isHost(dst)); + } + return ACLBuilder.normalizeIdentifier(hostPart, isHost(hostPart)) + ":" + ports; + }); + } + + // Normalize SSH Rules + if (this.ssh) { + for (const rule of this.ssh) { + rule.src = rule.src.map(id => ACLBuilder.normalizeIdentifier(id, isHost(id))); + rule.dst = rule.dst.map(id => ACLBuilder.normalizeIdentifier(id, isHost(id))); + // Note: rule.users are Unix usernames, they don't need @ + } + } + } + + private static normalizeIdentifier(id: string, isHost: boolean): string { + if (!id || id === "*" || id.includes("@") || id.includes("/") || id.startsWith("autogroup:") || ACLBuilder.getPrefix(id) !== null || isValidIP(id) || isHost) { + return id; + } + // If it's a bare name (not group:, not tag:, no @, not wildcard, not CIDR, not IP, not a defined host), it's a user. + // Headscale/Tailscale Go v2 parser requires an @ for user identifiers. + return id + "@"; } private static getPrefix(name: string): PrefixType | null { @@ -164,11 +209,11 @@ export class ACLBuilder implements ACL { return { prefixed, stripped } } - static normalizeTag(tag: string): {prefixed: string, stripped: string} { + static normalizeTag(tag: string): { prefixed: string, stripped: string } { return ACLBuilder.normalizePrefix(tag, "tag") } - static normalizeGroup(group: string): {prefixed: string, stripped: string} { + static normalizeGroup(group: string): { prefixed: string, stripped: string } { return ACLBuilder.normalizePrefix(group, "group") } @@ -203,10 +248,10 @@ export class ACLBuilder implements ACL { } static validateHostValue(value: string): string { - if(isValidIP(value)) { + if (isValidIP(value)) { return value } - if(isValidCIDR(value)) { + if (isValidCIDR(value)) { return value } throw new Error("Invalid Host IP or CIDR") @@ -232,7 +277,7 @@ export class ACLBuilder implements ACL { createHost(name: string, cidr: string) { - if(this.getHostCIDR(name) !== undefined) { + if (this.getHostCIDR(name) !== undefined) { throw new Error(`host "${name}" already exists`) } this.setHost(name, cidr) @@ -259,7 +304,7 @@ export class ACLBuilder implements ACL { } const hosts: AclHosts = {} - Object.entries(this.hosts).forEach(([name, value])=>{ + Object.entries(this.hosts).forEach(([name, value]) => { hosts[name === nameOld ? nameNew : name] = value }) this.hosts = hosts @@ -292,7 +337,7 @@ export class ACLBuilder implements ACL { } // remove group from SSH - if (this.ssh !== undefined){ + if (this.ssh !== undefined) { for (const ssh of this.ssh) { ssh.src = ssh.src.filter(s => s !== name) ssh.dst = ssh.dst.filter(d => d !== name) @@ -356,18 +401,19 @@ export class ACLBuilder implements ACL { const { prefixed } = ACLBuilder.normalizePrefix(name, 'tag') const ownersAll = [...owners] this.tagOwners[prefixed] = ownersAll + this.normalize() } getTagNames(withPrefix: boolean = false): string[] { return Object.keys(this.tagOwners).map(name => { - let {stripped, prefixed} = ACLBuilder.normalizePrefix(name, 'tag') + let { stripped, prefixed } = ACLBuilder.normalizePrefix(name, 'tag') return withPrefix ? prefixed : stripped }) } - getTagOwners(name: string): string[]{ + getTagOwners(name: string): string[] { const { stripped, prefixed } = ACLBuilder.normalizePrefix(name, 'tag') - const owners = this.tagOwners[prefixed] + const owners = this.tagOwners[prefixed] if (owners === undefined) { throw new Error(`Tag ${stripped} does not exist`) } @@ -414,13 +460,13 @@ export class ACLBuilder implements ACL { } // remove tag from ACLs - for (const acl of this.acls){ + for (const acl of this.acls) { acl.src = acl.src.filter(s => s !== prefixed); acl.dst = acl.dst.filter(d => d !== prefixed); } // remove tag from SSH - if (this.ssh !== undefined){ + if (this.ssh !== undefined) { for (const ssh of this.ssh) { ssh.src = ssh.src.filter(s => s !== prefixed) ssh.dst = ssh.dst.filter(d => d !== prefixed) @@ -495,6 +541,7 @@ export class ACLBuilder implements ACL { const { prefixed } = ACLBuilder.normalizePrefix(name, 'group') this.groups[prefixed] = [...members] + this.normalize() } getGroupByName(name: string): string[] { @@ -541,7 +588,7 @@ export class ACLBuilder implements ACL { } // remove group from SSH policies - if (this.ssh !== undefined){ + if (this.ssh !== undefined) { for (const ssh of this.ssh) { ssh.src = ssh.src.filter(s => s !== prefixed) } @@ -562,15 +609,15 @@ export class ACLBuilder implements ACL { * setPolicyProto(idx, proto) */ - public static getPolicyDstHost(dst: string): string { - const i = dst.lastIndexOf(':') - return i < 0 ? dst : dst.substring(0, i) - } + public static getPolicyDstHost(dst: string): string { + const i = dst.lastIndexOf(':') + return i < 0 ? dst : dst.substring(0, i) + } - public static getPolicyDstPorts(dst: string): string { - const i = dst.lastIndexOf(':') - return i < 0 ? dst : dst.substring(i+1, dst.length) - } + public static getPolicyDstPorts(dst: string): string { + const i = dst.lastIndexOf(':') + return i < 0 ? dst : dst.substring(i + 1, dst.length) + } createPolicy(policy: AclPolicy) { @@ -611,19 +658,21 @@ export class ACLBuilder implements ACL { "#ha-meta": HAMetaDefault, action: "accept", proto: undefined, - src: [ "*" ], - dst: [ "*:*" ], + src: ["*"], + dst: ["*:*"], } } setPolicySrc(idx: number, src: string[]) { this.validatePolicyIndex(idx) this.acls[idx].src = src + this.normalize() } setPolicyDst(idx: number, dst: string[]) { this.validatePolicyIndex(idx) this.acls[idx].dst = dst + this.normalize() } setPolicyProto(idx: number, proto: string | undefined) { @@ -660,19 +709,19 @@ export class ACLBuilder implements ACL { */ createSshRule(rule: AclSshRule) { - if (this.ssh === undefined){ + if (this.ssh === undefined) { this.ssh = [] } this.ssh.push(rule) } - getAllSshRules(): AclSshRules|undefined { + getAllSshRules(): AclSshRules | undefined { return this.ssh } getSshRule(idx: number): AclSshRule { this.validateSshRuleIndex(idx) - if (this.ssh !== undefined){ + if (this.ssh !== undefined) { return this.ssh[idx] } throw new Error("No SSH Rules defined") @@ -694,17 +743,18 @@ export class ACLBuilder implements ACL { } public static getPolicyTitle(pol: AclPolicy, idx: number): string { - const pfx = "#" + (idx + 1) + ": " - if (pol["#ha-meta"] === undefined || pol["#ha-meta"].name === "") { - return pfx + "Policy #" + (idx + 1) - } - return pfx + pol["#ha-meta"].name - } + const pfx = "#" + (idx + 1) + ": " + if (pol["#ha-meta"] === undefined || pol["#ha-meta"].name === "") { + return pfx + "Policy #" + (idx + 1) + } + return pfx + pol["#ha-meta"].name + } setSshRuleSrc(idx: number, src: string[]) { this.validateSshRuleIndex(idx) if (this.ssh != undefined) { this.ssh[idx].src = src + this.normalize() } } @@ -712,6 +762,7 @@ export class ACLBuilder implements ACL { this.validateSshRuleIndex(idx) if (this.ssh !== undefined) { this.ssh[idx].dst = dst + this.normalize() } } @@ -742,25 +793,28 @@ export class ACLBuilder implements ACL { } } -export async function saveConfig(acl: ACLBuilder, ToastStore: ToastStore, loading?: {setLoadingTrue: ()=>void, setLoadingFalse: ()=>void}) { - if(loading !== undefined){ +import { get } from 'svelte/store'; +import { _ } from 'svelte-i18n'; + +export async function saveConfig(acl: ACLBuilder, ToastStore: ToastStore, loading?: { setLoadingTrue: () => void, setLoadingFalse: () => void }) { + if (loading !== undefined) { loading.setLoadingTrue() } //loading = true try { await setPolicy(acl) - if(ToastStore !== undefined){ - toastSuccess('Saved ACL Configuration', ToastStore) + if (ToastStore !== undefined) { + toastSuccess(get(_)( 'acls.configSaved' ), ToastStore) } - } catch(err) { - if (err instanceof Error){ - if(ToastStore !== undefined){ + } catch (err) { + if (err instanceof Error) { + if (ToastStore !== undefined) { toastError('', ToastStore, err) } } debug(err) } finally { - if(loading !== undefined){ + if (loading !== undefined) { loading.setLoadingFalse() } } diff --git a/src/lib/common/api/base.ts b/src/lib/common/api/base.ts index 42214b8..610e4a3 100644 --- a/src/lib/common/api/base.ts +++ b/src/lib/common/api/base.ts @@ -58,19 +58,52 @@ function headers(): { headers: HeadersInit } { }; } +function mergeHeaders(initHeaders?: HeadersInit, includeJsonBody: boolean = false): Headers { + const result = new Headers(headers().headers); + + if (initHeaders !== undefined) { + const provided = new Headers(initHeaders); + provided.forEach((value, key) => { + result.set(key, value); + }); + } + + if (includeJsonBody && !result.has('Content-Type')) { + result.set('Content-Type', 'application/json'); + } + + return result; +} + export function toUrl(path: string): string { - return new URL(path, App.apiUrl.value).href + let base = App.apiUrl.value; + if (!base && typeof window !== 'undefined') { + base = window.location.origin; + } + if (!base.endsWith('/')) { + base += '/'; + } + if (path.startsWith('/')) { + path = path.substring(1); + } + return new URL(path, base).href; } async function apiFetch(path: string, init?: RequestInit, verbose: boolean = false): Promise { try { - const response = await fetch(toUrl(path), { ...headers(), ...init }); + const response = await fetch(toUrl(path), { + ...init, + headers: mergeHeaders(init?.headers, init?.body !== undefined), + }); if (verbose) { debug(response); } const apiResponse = await toApiResponse(response); - if (App.apiKeyInfo.value.authorized === null) { - App.apiKeyInfo.value.authorized = true + if (App.apiKeyInfo.value.authorized !== true) { + App.apiKeyInfo.value = { + ...App.apiKeyInfo.value, + authorized: true, + }; } return apiResponse; } catch (err) { @@ -95,22 +128,28 @@ export async function apiDelete(path: string, init?: RequestInit): Promise export async function apiPost( path: string, - data: unknown = null, + data?: unknown, init?: RequestInit, verbose: boolean = false, ): Promise { - const body = JSON.stringify(data ?? {}); - return await apiFetch(path, { method: 'POST', body, ...init }, verbose); + const requestInit: RequestInit = { method: 'POST', ...init }; + if (data !== undefined) { + requestInit.body = JSON.stringify(data); + } + return await apiFetch(path, requestInit, verbose); } export async function apiPut( path: string, - data: unknown = null, + data?: unknown, init?: RequestInit, verbose: boolean = false, ): Promise { - const body = JSON.stringify(data ?? {}); - return await apiFetch(path, { method: 'PUT', body, ...init }, verbose); + const requestInit: RequestInit = { method: 'PUT', ...init }; + if (data !== undefined) { + requestInit.body = JSON.stringify(data); + } + return await apiFetch(path, requestInit, verbose); } export async function apiTest(): Promise { diff --git a/src/lib/common/api/create.ts b/src/lib/common/api/create.ts index 7666859..0b7ed21 100644 --- a/src/lib/common/api/create.ts +++ b/src/lib/common/api/create.ts @@ -9,14 +9,16 @@ import { } from '$lib/common/types'; import { debug } from '$lib/common/debug'; import { API_URL_APIKEY, API_URL_NODE, API_URL_PREAUTHKEY, API_URL_USER } from './url'; +import { mapApiPreAuthKey } from './mappers'; -export async function createApiKey() { - // create 90-day API Key +export async function createApiKey(expirationDays?: number) { + // create API Key with custom expiration (default: 90 days) + const days = expirationDays ?? 90; const date = new Date(); - date.setDate(date.getDate() + 90); - const data = { expiration: date.toISOString() }; + date.setDate(date.getDate() + days); + const data = days > 0 ? { expiration: date.toISOString() } : {}; // no expiration if days <= 0 const { apiKey } = await apiPost(API_URL_APIKEY, data); - debug('Created API Key "...' + apiKey.slice(-10) + '"') + debug('Created API Key "...' + apiKey.slice(-10) + '" (expires in ' + days + ' days)') return apiKey; } @@ -31,8 +33,11 @@ export async function createUser(username: string): Promise { } export async function createNode(key: string, username: string): Promise { - const data = '?user=' + username + '&key=' + key; - const { node } = await apiPost(API_URL_NODE + '/register' + data) + const params = new URLSearchParams({ + user: username, + key, + }); + const { node } = await apiPost(`${API_URL_NODE}/register?${params.toString()}`); debug('Created Node "' + node.givenName + '" for user "' + username + '"'); return node; } @@ -42,14 +47,16 @@ export async function createPreAuthKey( ephemeral: boolean, reusable: boolean, expiration: Date | string, + tags: string[] = [], ) { const data = { user: user.id, reusable, ephemeral, expiration: new Date(expiration).toISOString(), + aclTags: tags.map((tag) => (tag.startsWith('tag:') ? tag : 'tag:' + tag)), }; const { preAuthKey } = await apiPost(API_URL_PREAUTHKEY, data); debug('Created PreAuthKey for user "' + user.name + '"'); - return preAuthKey; + return mapApiPreAuthKey(preAuthKey, user); } diff --git a/src/lib/common/api/delete.ts b/src/lib/common/api/delete.ts index 0ea18a7..3e05210 100644 --- a/src/lib/common/api/delete.ts +++ b/src/lib/common/api/delete.ts @@ -4,6 +4,20 @@ import { debug } from '../debug'; import { API_URL_APIKEY, API_URL_NODE, API_URL_USER } from './url'; import { App } from '$lib/States.svelte'; +/** + * Extract raw prefix from formatted prefix returned by headscale API + * - New format (12-char): "hskey-api-XXXXXXXXXXXX-***" -> "XXXXXXXXXXXX" + * - Legacy format (7-char): "XXXXXXX***" -> "XXXXXXX" + */ +function extractRawPrefix(formattedPrefix: string): string { + // Remove "hskey-api-" prefix and "-***" suffix for new format + if (formattedPrefix.startsWith('hskey-api-')) { + return formattedPrefix.replace('hskey-api-', '').replace('-***', ''); + } + // Remove "***" suffix for legacy format + return formattedPrefix.replace('***', ''); +} + export async function expireApiKey(apiKey: string) { if (apiKey.indexOf('.') > -1) { apiKey = apiKey.split('.').at(0) || ''; @@ -12,8 +26,10 @@ export async function expireApiKey(apiKey: string) { debug('Invalid API Key/Prefix'); return; } + // Extract raw prefix if it's formatted + const rawPrefix = extractRawPrefix(apiKey); try { - await apiPost(`${API_URL_APIKEY}/expire`, { prefix: apiKey }); + await apiPost(`${API_URL_APIKEY}/expire`, { prefix: rawPrefix }); debug('Expired API Key with Prefix ' + apiKey); } catch (error) { debug(error); @@ -42,4 +58,24 @@ export async function deleteNode(node: Node): Promise { debug(error); return false; } +} + +export async function deleteApiKey(idOrPrefix: string | number): Promise { + try { + let path: string; + if (typeof idOrPrefix === 'number') { + // Delete by ID using query parameter + path = `${API_URL_APIKEY}?id=${idOrPrefix}`; + } else { + // Extract raw prefix from formatted prefix before deleting + const rawPrefix = extractRawPrefix(idOrPrefix); + path = `${API_URL_APIKEY}/${rawPrefix}`; + } + await apiDelete(path); + debug('Deleted API Key: ' + idOrPrefix); + return true; + } catch (error) { + debug(error); + return false; + } } \ No newline at end of file diff --git a/src/lib/common/api/get.ts b/src/lib/common/api/get.ts index 0b2936e..c7b0196 100644 --- a/src/lib/common/api/get.ts +++ b/src/lib/common/api/get.ts @@ -1,5 +1,7 @@ -import { API_URL_NODE, API_URL_POLICY, API_URL_PREAUTHKEY, API_URL_USER, apiGet } from '$lib/common/api'; +import { API_URL_APIKEY, API_URL_NODE, API_URL_POLICY, API_URL_PREAUTHKEY, API_URL_USER, apiGet } from '$lib/common/api'; import type { + ApiApiKeys, + ApiKey, ApiNodes, ApiPolicy, ApiPreAuthKeys, @@ -9,31 +11,42 @@ import type { User, } from '$lib/common/types'; import { debug } from '../debug'; +import { mapApiPreAuthKeys } from './mappers'; export async function getPreAuthKeys( user_ids?: string[], init?: RequestInit, ): Promise { - if (user_ids == undefined) { - user_ids = (await getUsers(init)).map((u) => u.id); - } - const promises: Promise[] = []; - let preAuthKeysAll: PreAuthKey[] = []; + const { preAuthKeys } = await apiGet(API_URL_PREAUTHKEY, init); + const allowedUsers = user_ids !== undefined ? new Set(user_ids.filter((id) => id !== '')) : undefined; + const grouped = new Map(); - user_ids.forEach(async (user_id: string) => { - if(user_id != ""){ - promises.push( - apiGet(API_URL_PREAUTHKEY + '?user=' + user_id, init), - ); + for (const key of preAuthKeys ?? []) { + const userId = String(key.user?.id ?? ''); + if (!userId) { + debug('Skipping PreAuthKey without user information', key); + continue; } - }); + if (allowedUsers && !allowedUsers.has(userId)) { + continue; + } + const group = grouped.get(userId) ?? []; + group.push(key); + grouped.set(userId, group); + } - promises.forEach(async (p) => { - const { preAuthKeys } = await p; - preAuthKeysAll = preAuthKeysAll.concat(preAuthKeys); + let preAuthKeysAll: PreAuthKey[] = []; + grouped.forEach((keys, userId) => { + const user = keys[0]?.user; + if (!user) { + return; + } + const mappedKeys = mapApiPreAuthKeys(keys, user); + preAuthKeysAll = preAuthKeysAll.concat(mappedKeys); + debug(`Mapped ${mappedKeys.length} PreAuthKeys for user ${userId}`); }); - await Promise.all(promises); + debug(`Total PreAuthKeys loaded: ${preAuthKeysAll.length}`); return preAuthKeysAll; } @@ -64,7 +77,24 @@ export async function getNodes(): Promise { return nodes; } +export async function getNode(nodeId: string | number): Promise { + const { node } = await apiGet<{ node: Node }>(`${API_URL_NODE}/${nodeId}`); + debug('Fetched Node ID:', nodeId); + return node; +} + export async function getPolicy(): Promise { const { policy } = await apiGet(API_URL_POLICY) return policy } + +export async function getApiKeys(init?: RequestInit): Promise { + const { apiKeys } = await apiGet(API_URL_APIKEY, init); + return apiKeys; +} + +export async function getHealth(): Promise<{ databaseConnectivity: boolean }> { + const { databaseConnectivity } = await apiGet<{ databaseConnectivity: boolean }>('/api/v1/health'); + debug('Health check - DB connectivity:', databaseConnectivity); + return { databaseConnectivity }; +} diff --git a/src/lib/common/api/mappers.ts b/src/lib/common/api/mappers.ts new file mode 100644 index 0000000..a53ac0e --- /dev/null +++ b/src/lib/common/api/mappers.ts @@ -0,0 +1,73 @@ +/** + * API Response Mappers + * + * Converts API responses to frontend types with proper handling of legacy/new formats + * and missing fields. + */ + +import { PreAuthKey, type User } from '$lib/common/types'; +import { debug } from '../debug'; + +/** + * Maps raw API response to PreAuthKey object + * Handles both new and legacy (old format) pre-auth keys + */ +export function mapApiPreAuthKey(data: any, user: User): PreAuthKey { + // Handle snake_case from gRPC-Gateway + const id = data.id || data.ID || ''; + const key = data.key || data.Key || ''; + const reusable = data.reusable ?? data.Reusable ?? false; + const ephemeral = data.ephemeral ?? data.Ephemeral ?? false; + const used = data.used ?? data.Used ?? false; + const expiration = data.expiration || data.Expiration || ''; + const createdAt = data.createdAt || data.CreatedAt || data.created_at || ''; + const aclTags = data.aclTags || data.AclTags || data.acl_tags || []; + + // Validate required fields + if (!id || !key) { + debug('Invalid PreAuthKey data:', { id, key }); + throw new Error('Invalid PreAuthKey: missing id or key'); + } + + // Create PreAuthKey instance + const pak = new PreAuthKey( + user, + String(id), + key, + Boolean(reusable), + Boolean(ephemeral), + Boolean(used), + String(expiration), + String(createdAt), + Array.isArray(aclTags) ? aclTags : [] + ); + + debug('Mapped PreAuthKey:', { + id: pak.id, + keyLen: pak.key.length, + keyPreview: pak.key.substring(0, 20), + reusable: pak.reusable, + ephemeral: pak.ephemeral, + used: pak.used, + isLegacy: !pak.key.includes('*') && !pak.key.startsWith('hskey-auth-'), + hasExpiration: !!pak.expiration + }); + + return pak; +} + +/** + * Maps raw API response list to PreAuthKey array + */ +export function mapApiPreAuthKeys(dataList: any[], user: User): PreAuthKey[] { + return dataList + .map(data => { + try { + return mapApiPreAuthKey(data, user); + } catch (e) { + debug('Failed to map PreAuthKey:', data, e); + return null; + } + }) + .filter((pak): pak is PreAuthKey => pak !== null); +} diff --git a/src/lib/common/api/modify.ts b/src/lib/common/api/modify.ts index d5e176a..012f9da 100644 --- a/src/lib/common/api/modify.ts +++ b/src/lib/common/api/modify.ts @@ -30,22 +30,26 @@ export async function renameNode(n: Node, nameNew: string): Promise { } export async function changeNodeOwner(n: Node, newUserID: string): Promise { - const path = `${API_URL_NODE}/${n.id}/user`; - const { node } = await apiPost(path, {user: newUserID}); - debug('Re-assigned Node from "' + n.user.name + '" to "' + node.user.name + '"'); - return node; + throw new Error( + `Headscale 0.28.0 does not expose a public node owner reassignment endpoint (${n.id} -> ${newUserID}).`, + ); } export async function expirePreAuthKey(pak: PreAuthKey) { const path = `${API_URL_PREAUTHKEY}/expire`; - const data = { user: pak.user.id, key: pak.key }; + const data = { id: pak.id }; await apiPost(path, data); } -export async function expireNode(n: Node): Promise { - const path = `${API_URL_NODE}/${n.id}/expire`; - const { node } = await apiPost(path, undefined); - debug('Expired Node "' + n.givenName + '"'); +export async function expireNode(n: Node, date?: string): Promise { + const params = new URLSearchParams(); + if (date) { + params.set('expiry', date); + } + const suffix = params.size > 0 ? `?${params.toString()}` : ''; + const path = `${API_URL_NODE}/${n.id}/expire${suffix}`; + const { node } = await apiPost(path); + debug('Expired Node "' + n.givenName + '"' + (date ? ' at ' + date : '')); return node; } @@ -108,3 +112,13 @@ export async function refreshApiKey() { App.apiKeyInfo.value.informedExpiringSoon = false App.apiKeyInfo.value.informedUnauthorized = false } + +export async function backfillNodeIPs(confirmed: boolean = false): Promise { + const params = new URLSearchParams({ + confirmed: String(confirmed), + }); + const path = `${API_URL_NODE}/backfillips?${params.toString()}`; + const { changes } = await apiPost<{ changes: string[] }>(path); + debug('BackfillNodeIPs:', confirmed ? 'Applied' : 'Dry run', '- Changes:', changes.length); + return changes; +} diff --git a/src/lib/common/debug.ts b/src/lib/common/debug.ts index 5fd8a9d..57908c6 100644 --- a/src/lib/common/debug.ts +++ b/src/lib/common/debug.ts @@ -1,6 +1,6 @@ import { App } from "$lib/States.svelte"; -export const version = '0.26.0'; +export const version = '0.28.0'; export function debug(...data: unknown[]) { // output if console debugging is enabled diff --git a/src/lib/common/errors.ts b/src/lib/common/errors.ts index 36b11ce..3322ec4 100644 --- a/src/lib/common/errors.ts +++ b/src/lib/common/errors.ts @@ -3,6 +3,8 @@ import { informUserUnauthorized } from '$lib/States.svelte'; import type { ToastStore } from '@skeletonlabs/skeleton'; import { debug } from './debug'; +import { _ } from 'svelte-i18n'; +import { get } from 'svelte/store'; export class ApiAuthError extends Error { constructor() { @@ -23,3 +25,22 @@ export function createPopulateErrorHandler(ToastStore: ToastStore) { debug('Error Handler:', err); }; } + +export function localizeError(err: unknown): string { + const errorMsg = err instanceof Error ? err.message : String(err); + const translate = get(_); + + if (errorMsg.includes('cannot remove all tags from a node')) { + return translate('cards.cannotRemoveAllTags'); + } + + if (errorMsg.includes('re-authenticating with') || errorMsg.includes('force-reauth')) { + return translate('cards.taggedToUserReauthRequired'); + } + + if (errorMsg.includes('are invalid or not permitted')) { + return translate('cards.tagsNotPermitted'); + } + + return errorMsg; +} diff --git a/src/lib/common/export.ts b/src/lib/common/export.ts new file mode 100644 index 0000000..5916aa4 --- /dev/null +++ b/src/lib/common/export.ts @@ -0,0 +1,257 @@ +import type { Node, User, PreAuthKey, ApiKey } from './types'; +import { getPolicy } from './api'; +import { App } from '$lib/States.svelte'; + +export type ExportFormat = 'json' | 'csv' | 'yaml'; +export type ExportResource = 'users' | 'nodes' | 'preAuthKeys' | 'apiKeys' | 'policy'; + +export type ExportOptions = { + format: ExportFormat; + resources: ExportResource[]; + includeMetadata?: boolean; +}; + +function downloadFile(blob: Blob, filename: string) { + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = filename; + a.click(); + URL.revokeObjectURL(url); +} + +export function downloadJSON(data: any, filename: string) { + const json = JSON.stringify(data, null, 2); + const blob = new Blob([json], { type: 'application/json' }); + downloadFile(blob, filename); +} + +export function downloadCSV(data: any[], filename: string) { + if (data.length === 0) { + return; + } + + // Extract all unique keys from all objects + const keys = Array.from( + new Set(data.flatMap((item) => Object.keys(item))) + ); + + // CSV header + const csvHeader = keys.join(','); + + // CSV rows + const csvRows = data.map((item) => + keys + .map((key) => { + const value = item[key]; + // Handle null/undefined + if (value === null || value === undefined) { + return ''; + } + // Convert to string + const strValue = String(value); + // Escape special characters (quotes, commas, newlines) + if ( + strValue.includes(',') || + strValue.includes('"') || + strValue.includes('\n') + ) { + return `"${strValue.replace(/"/g, '""')}"`; + } + return strValue; + }) + .join(',') + ); + + const csv = [csvHeader, ...csvRows].join('\n'); + const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); + downloadFile(blob, filename); +} + +// Flatten nested objects for CSV export +function flattenNode(node: Node) { + return { + id: node.id, + name: node.name, + givenName: node.givenName, + user: node.user.name, + ipAddresses: node.ipAddresses.join('; '), + online: node.online, + lastSeen: node.lastSeen || '', + createdAt: node.createdAt, + expiry: node.expiry || '', + registerMethod: node.registerMethod, + tags: node.tags.join('; '), + approvedRoutes: node.approvedRoutes.join('; '), + availableRoutes: node.availableRoutes.join('; '), + subnetRoutes: node.subnetRoutes.join('; '), + }; +} + +function flattenUser(user: User) { + return { + id: user.id, + name: user.name, + displayName: user.displayName || '', + email: user.email || '', + createdAt: user.createdAt, + provider: user.provider || '', + providerId: user.providerId || '', + }; +} + +function flattenPreAuthKey(key: PreAuthKey) { + return { + id: key.id, + key: key.key, + user: key.user.name, + reusable: key.reusable, + ephemeral: key.ephemeral, + used: key.used, + expiration: key.expiration, + createdAt: key.createdAt, + aclTags: key.aclTags.join('; '), + }; +} + +function flattenApiKey(key: ApiKey) { + return { + id: key.id, + prefix: key.prefix, + createdAt: key.createdAt, + lastSeen: key.lastSeen || '', + expiration: key.expiration || '', + }; +} + +export async function exportHeadscaleData(options: ExportOptions) { + const exportData: any = {}; + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + + if (options.includeMetadata) { + exportData.metadata = { + exportedAt: new Date().toISOString(), + apiUrl: App.apiUrl.value, + format: options.format, + resources: options.resources, + }; + } + + // Collect data for each resource + if (options.resources.includes('users')) { + exportData.users = App.users.value; + } + + if (options.resources.includes('nodes')) { + exportData.nodes = App.nodes.value; + } + + if (options.resources.includes('preAuthKeys')) { + exportData.preAuthKeys = App.preAuthKeys.value; + } + + if (options.resources.includes('apiKeys')) { + // API Keys need to be fetched separately if not already in App state + // For now, we'll skip this or require it to be fetched beforehand + // exportData.apiKeys = await getApiKeys(); + } + + if (options.resources.includes('policy')) { + try { + exportData.policy = await getPolicy(); + } catch (error) { + console.error('Failed to export policy:', error); + } + } + + const filename = `headscale-export-${timestamp}`; + + switch (options.format) { + case 'json': + downloadJSON(exportData, `${filename}.json`); + break; + + case 'csv': + // CSV needs separate files for each resource type + if (options.resources.includes('users') && exportData.users) { + downloadCSV( + exportData.users.map(flattenUser), + `${filename}-users.csv` + ); + } + if (options.resources.includes('nodes') && exportData.nodes) { + downloadCSV( + exportData.nodes.map(flattenNode), + `${filename}-nodes.csv` + ); + } + if (options.resources.includes('preAuthKeys') && exportData.preAuthKeys) { + downloadCSV( + exportData.preAuthKeys.map(flattenPreAuthKey), + `${filename}-preAuthKeys.csv` + ); + } + if (options.resources.includes('apiKeys') && exportData.apiKeys) { + downloadCSV( + exportData.apiKeys.map(flattenApiKey), + `${filename}-apiKeys.csv` + ); + } + // Policy is not suitable for CSV export + break; + + case 'yaml': + // YAML export would require additional library + // For now, we'll just export as JSON + downloadJSON(exportData, `${filename}.yaml`); + break; + } +} + +// Quick export functions for individual resources +export function exportUsers(format: 'json' | 'csv' = 'json') { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const filename = `headscale-users-${timestamp}`; + + if (format === 'json') { + downloadJSON(App.users.value, `${filename}.json`); + } else { + downloadCSV(App.users.value.map(flattenUser), `${filename}.csv`); + } +} + +export function exportNodes(format: 'json' | 'csv' = 'json') { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const filename = `headscale-nodes-${timestamp}`; + + if (format === 'json') { + downloadJSON(App.nodes.value, `${filename}.json`); + } else { + downloadCSV(App.nodes.value.map(flattenNode), `${filename}.csv`); + } +} + +export function exportPreAuthKeys(format: 'json' | 'csv' = 'json') { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const filename = `headscale-preAuthKeys-${timestamp}`; + + if (format === 'json') { + downloadJSON(App.preAuthKeys.value, `${filename}.json`); + } else { + downloadCSV(App.preAuthKeys.value.map(flattenPreAuthKey), `${filename}.csv`); + } +} + +export async function exportPolicy() { + const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); + const filename = `headscale-policy-${timestamp}.json`; + + try { + const policy = await getPolicy(); + // Policy is already a string (HuJSON format) + const blob = new Blob([policy], { type: 'application/json' }); + downloadFile(blob, filename); + } catch (error) { + console.error('Failed to export policy:', error); + } +} diff --git a/src/lib/common/funcs.ts b/src/lib/common/funcs.ts index 0ca9c2f..cc014d3 100644 --- a/src/lib/common/funcs.ts +++ b/src/lib/common/funcs.ts @@ -4,6 +4,8 @@ import IPAddr from 'ipaddr.js'; import { debug } from './debug'; import DOMPurify from 'dompurify'; import type { Direction, Node, OnlineStatus, User } from './types'; +import { get } from 'svelte/store'; +import { locale as i18nLocale, _ } from 'svelte-i18n'; import { App } from '$lib/States.svelte'; export function clone(item: T): T { @@ -16,27 +18,35 @@ export function focus(el: HTMLElement | null) { } } +export function getUserAclName(user: User): string { + const name = user.email ? user.email : user.name; + if (name && !name.includes('@')) { + return name + '@'; + } + return name; +} + export function arraysEqual(a: T[], b: T[]): boolean { - if(a.length !== b.length){ + if (a.length !== b.length) { return false } return JSON.stringify(a) == JSON.stringify(b) - if (a === b){ + if (a === b) { return true; } - if (a == null || b == null){ + if (a == null || b == null) { return false; } - + if (a.length !== b.length) { return false; } for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]){ + if (a[i] !== b[i]) { return false; } } @@ -98,7 +108,7 @@ export function getTime( export function getTimeDifferenceMessage(time1: number): string { const difference = getTimeDifference(time1, new Date().getTime()); - return difference.finite ? difference.message : 'Does Not Expire'; + return difference.finite ? difference.message : (safeIsZh() ? '不过期' : 'Does Not Expire'); } export function getTimeDifferenceColor(td: TimeDifference): string { @@ -114,7 +124,7 @@ export function getTimeDifference(time1: number, time2?: number): TimeDifference return { future: true, finite: false, - message: 'Does Not Expire', + message: safeIsZh() ? '不过期' : 'Does Not Expire', }; } @@ -131,24 +141,40 @@ export function getTimeDifference(time1: number, time2?: number): TimeDifference const weeks = Math.floor(days / 7); const months = Math.floor(weeks / 4); - if (months > 0) { - message = `${months} month${months == 1 ? '' : 's'}`; - } else if (weeks > 0) { - message = `${weeks} week${weeks == 1 ? '' : 's'}`; - } else if (days > 0) { - message = `${days} day${days == 1 ? '' : 's'}`; - } else if (hours > 0) { - message = `${hours} hour${hours == 1 ? '' : 's'}`; - } else if (minutes > 0) { - message = `${minutes} minute${minutes == 1 ? '' : 's'}`; + if (safeIsZh()) { + if (months > 0) { + message = `${months}个月`; + } else if (weeks > 0) { + message = `${weeks}周`; + } else if (days > 0) { + message = `${days}天`; + } else if (hours > 0) { + message = `${hours}小时`; + } else if (minutes > 0) { + message = `${minutes}分钟`; + } else { + message = `${seconds}秒`; + } } else { - message = `${seconds} second${seconds == 1 ? '' : 's'}`; + if (months > 0) { + message = `${months} month${months == 1 ? '' : 's'}`; + } else if (weeks > 0) { + message = `${weeks} week${weeks == 1 ? '' : 's'}`; + } else if (days > 0) { + message = `${days} day${days == 1 ? '' : 's'}`; + } else if (hours > 0) { + message = `${hours} hour${hours == 1 ? '' : 's'}`; + } else if (minutes > 0) { + message = `${minutes} minute${minutes == 1 ? '' : 's'}`; + } else { + message = `${seconds} second${seconds == 1 ? '' : 's'}`; + } } return { future: isFuture, finite: true, - message: message + ` ${isFuture ? 'from now' : 'ago'}`, + message: safeIsZh() ? `${message}${isFuture ? '后' : '前'}` : message + ` ${isFuture ? 'from now' : 'ago'}`, }; } @@ -157,16 +183,34 @@ export function dateToStr(d: Date | string) { d = new Date(d); } - return d.toLocaleString('en-US', { + if (safeIsZh()) { + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + const hour = String(d.getHours()).padStart(2, '0'); + const minute = String(d.getMinutes()).padStart(2, '0'); + return `${year}-${month}-${day} ${hour}:${minute}`; + } + + return d.toLocaleString('en-GB', { day: '2-digit', - month: '2-digit', + month: 'short', year: 'numeric', - hour: 'numeric', + hour: '2-digit', minute: '2-digit', - //hour12: false + hour12: false }); } +function safeIsZh(): boolean { + try { + const lang = get(i18nLocale) ?? ''; + return lang === 'zh' || lang.startsWith('zh-'); + } catch { + return false; + } +} + export function toastSuccess(message: string, toastStore: ToastStore) { message = DOMPurify.sanitize(message) toastStore.trigger({ @@ -200,18 +244,22 @@ export function toastError(message: string, toastStore: ToastStore, error?: Erro export function copyToClipboard( s: string, toastStore?: ToastStore, - toastMessage = 'Copied to Clipboard!', + toastMessage?: string, ) { + const translate = get(i18nLocale); // This is actually the locale string, I need the formatter + // Wait, let's use the same pattern as errors.ts + const msg = toastMessage ?? get(_)( 'common.copySuccess' ); + navigator.clipboard .writeText(s) .then(() => { if (toastStore != undefined) { - toastSuccess(toastMessage, toastStore); + toastSuccess(msg, toastStore); } }) .catch(() => { if (toastStore) { - toastError('Failed to copy to clipboard!', toastStore); + toastError(get(_)( 'common.copyFailed' ), toastStore); } }); } @@ -219,7 +267,7 @@ export function copyToClipboard( export function isValidTag(tag: string): boolean { // the only restrictions I could find were to be all lowercase, no-spaces // I made it alphanumeric with dashes and underscores only - return new RegExp(/^[a-z0-9-_]+$/, 'g').test(tag); + return new RegExp(/^[a-z0-9-_]+$/).test(tag); } function getInverseMask(prefix: number, bitsTotal: number, bitsPart: number = 8) { @@ -245,7 +293,7 @@ export function isValidIP(addr: string): boolean { try { IPAddr.parse(addr) return true - } catch(err) { + } catch (err) { debug(err) return false } @@ -295,7 +343,7 @@ function makeDrawerSettings( export function openDrawer(drawerStore: DrawerStore, id: string, meta: unknown) { drawerStore.open(makeDrawerSettings(id, meta)); } -export function toOptions(values: string[]): {label: string, value:string}[] { +export function toOptions(values: string[]): { label: string, value: string }[] { return values.map(v => ({ label: v, value: v, @@ -389,7 +437,7 @@ export function filterUser(user: User, filterString: string, onlineStatus: Onlin } export function filterNode(node: Node, filterString: string, onlineStatus: OnlineStatus = "all"): boolean { - if((onlineStatus === "online" && !node.online) || (onlineStatus === "offline" && node.online)){ + if ((onlineStatus === "online" && !node.online) || (onlineStatus === "offline" && node.online)) { return false } @@ -401,15 +449,14 @@ export function filterNode(node: Node, filterString: string, onlineStatus: Onlin const r = RegExp(filterString); const getTag = (tag: string) => { if (tag.startsWith('tag:')) { - return tag.substring(0, 4); + return tag.substring(4); } return tag; }; return ( r.test(node.name) || r.test(node.givenName) || - node.forcedTags.map(getTag).some((tag) => r.test(tag)) || - node.validTags.map(getTag).some((tag) => r.test(tag)) + node.tags.map(getTag).some((tag) => r.test(tag)) ); } catch (err) { return true; @@ -418,13 +465,13 @@ export function filterNode(node: Node, filterString: string, onlineStatus: Onlin export function getSortedFilteredUsers( users: User[], - filterString:string, + filterString: string, sortMethod: string, sortDirection: Direction, onlineStatus: OnlineStatus, -){ +) { return getSortedUsers( - users.filter((user)=> filterUser(user, filterString, onlineStatus)), + users.filter((user) => filterUser(user, filterString, onlineStatus)), sortMethod, sortDirection, ) @@ -432,18 +479,18 @@ export function getSortedFilteredUsers( export function getSortedFilteredNodes( nodes: Node[], - filterString:string, + filterString: string, sortMethod: string, sortDirection: Direction, onlineStatus: OnlineStatus, ignoreRouteless: boolean = false, -){ +) { let nodesSortedFiltered = getSortedNodes( - nodes.filter((node)=> filterNode(node, filterString, onlineStatus)), + nodes.filter((node) => filterNode(node, filterString, onlineStatus)), sortMethod, sortDirection, ) - if(ignoreRouteless === true){ + if (ignoreRouteless === true) { return nodesSortedFiltered.filter((n) => { return n.availableRoutes.length > 0; }) diff --git a/src/lib/common/themes.ts b/src/lib/common/themes.ts index 9a8f265..72d82f6 100644 --- a/src/lib/common/themes.ts +++ b/src/lib/common/themes.ts @@ -9,6 +9,7 @@ export const ALL_THEMES = [ 'hamlindigo', 'gold-nouveau', 'crimson', + 'decula', ]; export function setTheme(theme: string) { diff --git a/src/lib/common/types.ts b/src/lib/common/types.ts index b2843e5..f5565fe 100644 --- a/src/lib/common/types.ts +++ b/src/lib/common/types.ts @@ -22,7 +22,21 @@ export type ExpirationMessage = { message: string; color: string; }; +export type SystemStats = { + totalUsers: number; + totalNodes: number; + onlineNodes: number; + offlineNodes: number; + totalRoutes: number; + enabledRoutes: number; + totalPreAuthKeys: number; + validPreAuthKeys: number; +}; +export type HealthStatus = { + databaseConnectivity: boolean; + lastChecked: Date; +}; export function isNamed(item: unknown): item is Named { if (item != null && typeof item === 'object') { return ( @@ -133,18 +147,15 @@ export type Node = { name: string; user: User; lastSeen: string | null; - lastSuccessfulUpdate: string | null; expiry: string | null; - preAuthKey: string | null; + preAuthKey: PreAuthKey | null; createdAt: string; registerMethod: | 'REGISTER_METHOD_UNSPECIFIED' | 'REGISTER_METHOD_AUTH_KEY' | 'REGISTER_METHOD_CLI' | 'REGISTER_METHOD_OIDC'; - forcedTags: string[]; - invalidTags: string[]; - validTags: string[]; + tags: string[]; givenName: string; online: boolean; approvedRoutes: string[]; @@ -169,7 +180,7 @@ export type ApiKey = { createdAt: string; prefix: string; expiration: string; - lastSeen: string; + lastSeen: string | null; }; export type ApiApiKey = { apiKey: string; diff --git a/src/lib/i18n.ts b/src/lib/i18n.ts new file mode 100644 index 0000000..b13c2be --- /dev/null +++ b/src/lib/i18n.ts @@ -0,0 +1,111 @@ +import { browser } from '$app/environment'; +import { init, register, locale } from 'svelte-i18n'; + +export const SUPPORTED_LOCALES = ['en', 'zh'] as const; +export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]; + +export const DEFAULT_LOCALE: SupportedLocale = 'en'; +export const LOCALE_STORAGE_KEY = 'locale'; +const LOCALE_COOKIE_KEY = 'locale'; +const LOCALE_COOKIE_MAX_AGE = 60 * 60 * 24 * 365; + +export const LOCALE_OPTIONS = [ + { + code: 'en', + label: 'English', + description: 'Use English throughout the interface.', + }, + { + code: 'zh', + label: '简体中文', + description: '使用简体中文浏览和管理整个控制台。', + }, +] as const; + +register('en', () => import('./locales/en.json')); +register('zh', () => import('./locales/zh.json')); + +function normalizeLocale(value?: string | null): SupportedLocale | null { + if (!value) { + return null; + } + + let candidate = value.trim(); + + try { + const parsed = JSON.parse(candidate); + if (typeof parsed === 'string') { + candidate = parsed.trim(); + } + } catch { + // Ignore non-JSON values and fall back to the raw string. + } + + const normalized = candidate.toLowerCase(); + + if (normalized === 'zh' || normalized.startsWith('zh-')) { + return 'zh'; + } + + if (normalized === 'en' || normalized.startsWith('en-')) { + return 'en'; + } + + return null; +} + +function readLocaleFromCookie(): SupportedLocale | null { + if (!browser) { + return null; + } + + const match = document.cookie.match(/(?:^|;\s*)locale=([^;]+)/); + return normalizeLocale(match ? decodeURIComponent(match[1]) : null); +} + +function readLocaleFromStorage(): SupportedLocale | null { + if (!browser) { + return null; + } + + return normalizeLocale(window.localStorage.getItem(LOCALE_STORAGE_KEY)); +} + +function readNavigatorLocale(): SupportedLocale { + if (!browser) { + return DEFAULT_LOCALE; + } + + return normalizeLocale(window.navigator.language) ?? DEFAULT_LOCALE; +} + +export function hasStoredLocalePreference(): boolean { + return readLocaleFromCookie() !== null || readLocaleFromStorage() !== null; +} + +export function getStoredLocale(): SupportedLocale | null { + return readLocaleFromCookie() ?? readLocaleFromStorage(); +} + +export function getInitialLocale(): SupportedLocale { + return getStoredLocale() ?? readNavigatorLocale(); +} + +export function persistLocalePreference(localeCode: SupportedLocale): SupportedLocale { + if (!browser) { + return localeCode; + } + + window.localStorage.setItem(LOCALE_STORAGE_KEY, JSON.stringify(localeCode)); + document.cookie = `${LOCALE_COOKIE_KEY}=${encodeURIComponent(localeCode)}; Max-Age=${LOCALE_COOKIE_MAX_AGE}; Path=/; SameSite=Lax`; + document.documentElement.lang = localeCode; + return localeCode; +} + +init({ + fallbackLocale: DEFAULT_LOCALE, + initialLocale: getInitialLocale(), +}); + +// Set the locale immediately for SSR compatibility +locale.set(getInitialLocale()); diff --git a/src/lib/locales/en.json b/src/lib/locales/en.json new file mode 100644 index 0000000..ccccee8 --- /dev/null +++ b/src/lib/locales/en.json @@ -0,0 +1,345 @@ +{ + "app": { + "title": "Headscale Admin", + "github": "GitHub" + }, + "navigation": { + "title": "Navigation", + "home": "Home", + "users": "Users", + "nodes": "Nodes", + "routes": "Routes", + "acls": "ACLs", + "status": "System Status", + "settings": "Settings", + "deploy": "Deploy" + }, + "settings": { + "title": "Settings", + "apiUrl": "Headscale API URL", + "apiKey": "API Key", + "apiUrlPlaceholder": "Enter the Headscale API URL", + "apiKeyPlaceholder": "Enter your API key", + "apiTtl": "Auto-refresh interval (seconds)", + "theme": "Theme", + "language": "Interface Language", + "debugging": "Debug Tools", + "save": "Save Settings", + "authorized": "Authorized", + "notAuthorized": "Not Authorized", + "expiresIn": "Time Remaining", + "checkingAuth": "Validating API authorization...", + "savedSettings": "Settings saved", + "logUsers": "Log Users", + "logNodes": "Log Nodes", + "logPreAuthKeys": "Log PreAuth Keys", + "logApiKeyInfo": "Log API Key Info", + "showApiKey": "Show API key", + "hideApiKey": "Hide API key", + "refreshApiKey": "Rotate API Key", + "rememberMe": "Remember the API key in this browser", + "apiKeysManagement": "API Key Management", + "apiKeysList": "API Keys", + "createNewApiKey": "Create API Key", + "expirationDays": "Expiration (days)", + "neverExpire": "Never Expires", + "prefix": "Prefix", + "createdAt": "Created At", + "lastSeen": "Last Seen", + "expiration": "Expiration", + "deleteApiKeyConfirm": "Delete this API key?", + "deleteApiKeyWarning": "This action cannot be undone. Any clients using this key will immediately lose access.", + "deletingCurrentKey": "Warning: you are deleting the API key currently in use.", + "apiKeyCreated": "API key created successfully", + "apiKeyDeleted": "API key deleted", + "loadingApiKeys": "Loading API keys...", + "noApiKeys": "No API keys found", + "unauthorizedMessage": "The API key is invalid or not authorized", + "expiringSoonMessage": "The API key is about to expire" + }, + "common": { + "close": "Close", + "cancel": "Cancel", + "confirm": "Confirm", + "delete": "Delete", + "edit": "Edit", + "save": "Save", + "create": "Create", + "loading": "Loading...", + "copyFailed": "Failed to copy to clipboard", + "copySuccess": "Copied to clipboard", + "name": "Name", + "email": "Email", + "user": "User", + "node": "Node", + "route": "Route", + "status": "Status", + "actions": "Actions", + "online": "Online", + "offline": "Offline", + "expired": "Expired", + "active": "Active", + "createdAt": "Created At", + "lastSeen": "Last Seen", + "hostname": "Hostname", + "addresses": "Addresses", + "tags": "Tags", + "owner": "Owner", + "routes": "Routes", + "all": "All", + "id": "ID", + "sort": "Sort", + "filter": "Filter", + "search": "Search...", + "createUser": "Create User", + "createNode": "Create Node", + "newUsername": "New username...", + "deviceKey": "Device key...", + "usernameAndKeyRequired": "Username and device key are required", + "createdUser": "User created", + "createdNode": "Node created", + "failedCreateUser": "Failed to create user", + "failedCreateNode": "Failed to create node", + "export": "Export", + "exportData": "Export Data", + "exportFormat": "Format", + "exportResources": "Resources", + "exportIncludeMetadata": "Include metadata", + "exportSuccess": "Data exported successfully", + "exportFailed": "Failed to export data", + "exportAll": "Export All", + "users": "Users", + "nodes": "Nodes", + "preAuthKeys": "PreAuth Keys", + "apiKeys": "API Keys", + "policy": "Policy", + "batchOperations": "Batch Actions", + "selectAll": "Select All", + "deselectAll": "Clear Selection", + "selectedCount": "{count} selected", + "batchDelete": "Delete Selected", + "batchSetTags": "Set Tags", + "batchDeleteConfirm": "Delete selected nodes?", + "batchDeleteWarning": "Are you sure you want to delete {count} node(s)? This action cannot be undone.", + "batchDeleted": "Deleted {count} node(s)", + "enterTags": "Enter tags separated by commas", + "tagsUpdated": "Updated tags for {count} node(s)", + "backfillNodeIPs": "Backfill Node IPs", + "backfillNodeIPsDesc": "Assign Headscale IP addresses to nodes that do not have any yet.", + "backfillConfirmDesc": "Only missing IP addresses will be filled in. Existing node addresses will not be changed. Review the pending changes below before applying them.", + "dryRun": "Preview", + "applyChanges": "Apply Changes", + "backfillChanges": "Pending Changes", + "noChangesNeeded": "No changes are needed", + "backfillCompleted": "Backfill completed: {count} change(s) applied", + "enableAll": "Enable All", + "disableAll": "Disable All", + "backToNodes": "Back to Nodes", + "notFound": "The requested item was not found" + }, + "status": { + "title": "System Status", + "healthCheck": "Health Check", + "monitorSystemHealth": "Monitor the core components of the Headscale environment in real time.", + "databaseConnectivity": "Database Connectivity", + "healthy": "Healthy", + "unhealthy": "Unhealthy", + "lastChecked": "Last Checked", + "systemStatistics": "System Statistics", + "totalUsers": "Total Users", + "totalNodes": "Total Nodes", + "onlineNodes": "Online Nodes", + "offlineNodes": "Offline Nodes", + "totalRoutes": "Total Routes", + "enabledRoutes": "Enabled Routes", + "totalPreAuthKeys": "Total PreAuth Keys", + "validPreAuthKeys": "Valid PreAuth Keys", + "refreshing": "Refreshing...", + "refresh": "Refresh", + "autoRefresh": "Auto-refresh every 30 seconds" + }, + "users": { + "title": "Users", + "createUser": "Create User", + "displayName": "Display Name", + "provider": "Provider", + "email": "Email", + "nodes": "Nodes", + "preAuthKeys": "Pre-Auth Keys" + }, + "nodes": { + "title": "Nodes", + "createNode": "Create Node", + "registrationMethod": "Registration Method", + "expiresAt": "Expires At", + "info": "Details" + }, + "routes": { + "title": "Routes", + "enabled": "Enabled", + "advertised": "Advertised", + "destination": "Destination" + }, + "acls": { + "title": "ACLs", + "config": "Config", + "groups": "Groups", + "hosts": "Hosts", + "policies": "Policies", + "sshRules": "SSH Rules", + "tagOwners": "Tag Owners", + "hostCreated": "Host '{name}' created", + "tagCreated": "Tag '{name}' created", + "sshRuleCreated": "SSH rule #{count} created", + "policyCreated": "Policy #{count} created", + "groupCreated": "Group '{name}' created", + "configLoaded": "ACL policy loaded from the server", + "configLoadFailed": "Failed to load the ACL policy from the server", + "configSaved": "ACL configuration saved", + "createHost": "Create Host", + "createTag": "Create Tag", + "createSshRule": "Create SSH Rule", + "createPolicy": "Create Policy", + "createGroup": "Create Group", + "saveConfig": "Save Config", + "loadConfig": "Load Config", + "editConfig": "Edit Config", + "applyConfig": "Apply Config", + "cancelEditing": "Cancel Editing", + "resetConfig": "Reset Config" + }, + "deploy": { + "title": "Deploy", + "copyCommand": "Command copied to clipboard", + "general": "General", + "advertise": "Advertise", + "accept": "Accept", + "saveDefaults": "Save Defaults", + "savedDefaults": "Deployment defaults saved", + "shieldsUp": "Shields Up", + "shieldsUpHelp": "Block incoming connections", + "generateQR": "Generate QR Code", + "generateQRHelp": "Generate a QR code that can be scanned by the Tailscale client.", + "reset": "Reset", + "resetHelp": "Reset unspecified options to their default values", + "operator": "Operator", + "operatorHelp": "Run the client as a different local user (Unix only)", + "forceReauth": "Force Reauthentication", + "forceReauthHelp": "Require the client to authenticate with Headscale again", + "sshServer": "SSH Server", + "sshServerHelp": "Expose a local SSH server for administrators", + "preAuthKey": "PreAuth Key", + "preAuthKeyHelp": "Use a generated pre-auth key to register the node automatically for a specific user", + "unattended": "Unattended", + "unattendedHelp": "Run the Tailscale client in unattended mode on startup", + "allowLANAccess": "Allow LAN Access", + "allowLANAccessHelp": "Keep access to the local network while using an exit node", + "advertiseExitNode": "Advertise Exit Node", + "advertiseExitNodeHelp": "Allow other Tailnet nodes to use this device as a gateway", + "advertiseTags": "Advertise Tags", + "advertiseTagsHelp": "Apply these advertised tags when provisioning the node", + "advertiseRoutes": "Advertise Routes", + "advertiseRoutesHelp": "Subnets that should be reachable through this node", + "acceptDNS": "Accept DNS", + "acceptDNSHelp": "Accept DNS configuration distributed by Headscale", + "acceptRoutes": "Accept Routes", + "acceptRoutesHelp": "Accept subnets advertised by other nodes", + "exitNode": "Exit Node", + "exitNodeHelp": "Use the selected node as an exit node", + "validKeys": "valid key(s)", + "tagError": "Tags must use lowercase letters, digits, dashes, or underscores", + "cidrError": "Invalid CIDR format" + }, + "home": { + "title": "Home", + "totalUsers": "Total Users", + "onlineUsers": "Online Users", + "validPreAuthKeys": "Valid PreAuth Keys", + "totalNodes": "Total Nodes", + "onlineNodes": "Online Nodes", + "totalRoutes": "Total Routes", + "clickToView": "Click to view details" + }, + "cards": { + "autogroup": "Autogroup", + "provider": "Provider:", + "email": "Email:", + "displayName": "Display Name:", + "hostname": "Hostname:", + "created": "Created:", + "lastSeen": "Last Seen:", + "user": "User:", + "routes": "Routes:", + "owner": "Owner:", + "tags": "Tags:", + "registerMethod": "Registration Method:", + "expires": "Expires:", + "name": "Name:", + "info": "Info:", + "ipv4Address": "IPv4 Address:", + "onlineNow": "Online now", + "unspecified": "Unspecified", + "local": "Local", + "preAuthKey": "PreAuth Key", + "cli": "CLI", + "oidc": "OIDC", + "custom": "Custom", + "group": "Group", + "host": "Host", + "tag": "Tag", + "srcObject": "Source object...", + "dstObject": "Destination object...", + "dstPorts": "Destination ports...", + "selectOwners": "Select owners for {tagName}...", + "selectMembers": "Select members for {groupName}...", + "invalidHost": "Invalid host value", + "invalidPort": "Invalid port value", + "protocol": "Protocol:", + "any": "Any", + "tcp": "TCP", + "udp": "UDP", + "icmp": "ICMP", + "sources": "Sources:", + "destinations": "Destinations:", + "add": "Add", + "newOwner": "New Owner:", + "userNameEmpty": "User name cannot be empty", + "nodeNameEmpty": "Node name cannot be empty", + "sshRule": "SSH Rule", + "usernames": "Usernames:", + "advertisedTags": "Advertised Tags:", + "tagsPreventedByACL": "The following tags are blocked by the current ACL policy:", + "hideInvalid": "Hide Invalid", + "create": "Create", + "ephemeral": "Ephemeral", + "reusable": "Reusable", + "delete": "Delete", + "hostRenameWarning": "The host '{hostName}' has the same name as a user. Please rename the host.", + "deletedUser": "Deleted user \"{name}\" (ID: {id})", + "deletedMachine": "Deleted node \"{name}\" ({id})", + "failedDeleteUser": "Failed to delete user \"{name}\" ({id})", + "failedDeleteMachine": "Failed to delete node \"{name}\" ({id})", + "stillHasNodes": " The user still owns node(s).", + "invalidTags": "Invalid tags:", + "cannotRemoveAllTags": "Cannot remove all tags from a tagged node. At least one tag must remain.", + "tagsNotPermitted": "The requested tags are not defined in the ACL policy or are not permitted.", + "taggedToUserReauthRequired": "Headscale 0.28+ cannot move a tagged node back to a user directly. Re-authenticate the client with 'tailscale up --advertise-tags= --force-reauth'.", + "tagOwnershipWarning": "Adding tags will put this device into tagged-persona mode. In this mode, the node stops belonging to an individual user and is managed by tags instead. On Headscale 0.28+, this ownership change is effectively irreversible unless the device is re-authenticated. Continue?", + "tagsMissingInACL": "The following tags are not defined or allowed in the current ACL policy: {tags}", + "autoCreateTagsPrompt": "Would you like to automatically create these tags in the ACL policy?", + "tagsCreatedInACL": "Tags successfully created in the ACL policy.", + "failedToCreateTags": "Failed to auto-create tags in ACLs.", + "policyDeleted": "Policy #{number} deleted", + "sshRuleDeleted": "SSH rule #{number} deleted", + "groupDeleted": "Group '{name}' deleted", + "tagDeleted": "Tag '{name}' deleted", + "groupRenamedSuccess": "Group renamed from '{oldName}' to '{newName}'", + "tagRenamedSuccess": "Tag renamed from '{oldName}' to '{newName}'", + "membersOf": "Members", + "ownersOf": "Owners", + "hostDeleted": "Host '{name}' deleted", + "nodes": "Nodes:", + "used": "Used", + "expired": "Expired" + } +} diff --git a/src/lib/locales/zh.json b/src/lib/locales/zh.json new file mode 100644 index 0000000..bc653b2 --- /dev/null +++ b/src/lib/locales/zh.json @@ -0,0 +1,345 @@ +{ + "app": { + "title": "Headscale 管理台", + "github": "GitHub" + }, + "navigation": { + "title": "导航", + "home": "首页", + "users": "用户", + "nodes": "节点", + "routes": "路由", + "acls": "访问控制", + "status": "系统状态", + "settings": "设置", + "deploy": "部署" + }, + "settings": { + "title": "设置", + "apiUrl": "Headscale API 地址", + "apiKey": "API 密钥", + "apiUrlPlaceholder": "请输入 Headscale API 地址", + "apiKeyPlaceholder": "请输入 API 密钥", + "apiTtl": "自动刷新间隔(秒)", + "theme": "主题", + "language": "界面语言", + "debugging": "调试工具", + "save": "保存设置", + "authorized": "授权有效", + "notAuthorized": "未授权", + "expiresIn": "剩余有效期", + "checkingAuth": "正在验证 API 授权...", + "savedSettings": "设置已保存", + "logUsers": "输出用户数据", + "logNodes": "输出节点数据", + "logPreAuthKeys": "输出预授权密钥数据", + "logApiKeyInfo": "输出 API 密钥信息", + "showApiKey": "显示 API 密钥", + "hideApiKey": "隐藏 API 密钥", + "refreshApiKey": "轮换 API 密钥", + "rememberMe": "在当前浏览器中记住 API 密钥", + "apiKeysManagement": "API 密钥管理", + "apiKeysList": "API 密钥列表", + "createNewApiKey": "创建 API 密钥", + "expirationDays": "有效期(天)", + "neverExpire": "永不过期", + "prefix": "前缀", + "createdAt": "创建时间", + "lastSeen": "最后使用时间", + "expiration": "到期时间", + "deleteApiKeyConfirm": "确定要删除这个 API 密钥吗?", + "deleteApiKeyWarning": "此操作无法撤销。所有正在使用该密钥的客户端都会立即失去访问权限。", + "deletingCurrentKey": "警告:你正在删除当前正在使用的 API 密钥。", + "apiKeyCreated": "API 密钥创建成功", + "apiKeyDeleted": "API 密钥已删除", + "loadingApiKeys": "正在加载 API 密钥列表...", + "noApiKeys": "未找到 API 密钥", + "unauthorizedMessage": "API 密钥无效或未获授权", + "expiringSoonMessage": "API 密钥即将到期" + }, + "common": { + "close": "关闭", + "cancel": "取消", + "confirm": "确认", + "delete": "删除", + "edit": "编辑", + "save": "保存", + "create": "创建", + "loading": "加载中...", + "copyFailed": "复制到剪贴板失败", + "copySuccess": "已复制到剪贴板", + "name": "名称", + "email": "邮箱", + "user": "用户", + "node": "节点", + "route": "路由", + "status": "状态", + "actions": "操作", + "online": "在线", + "offline": "离线", + "expired": "已过期", + "active": "有效", + "createdAt": "创建时间", + "lastSeen": "最后活跃", + "hostname": "主机名", + "addresses": "地址", + "tags": "标签", + "owner": "归属用户", + "routes": "路由", + "all": "全部", + "id": "ID", + "sort": "排序", + "filter": "筛选", + "search": "搜索...", + "createUser": "创建用户", + "createNode": "创建节点", + "newUsername": "输入用户名...", + "deviceKey": "输入设备密钥...", + "usernameAndKeyRequired": "用户名和设备密钥均为必填项", + "createdUser": "用户已创建", + "createdNode": "节点已创建", + "failedCreateUser": "创建用户失败", + "failedCreateNode": "创建节点失败", + "export": "导出", + "exportData": "导出数据", + "exportFormat": "导出格式", + "exportResources": "导出资源", + "exportIncludeMetadata": "包含元数据", + "exportSuccess": "数据导出成功", + "exportFailed": "数据导出失败", + "exportAll": "全部导出", + "users": "用户", + "nodes": "节点", + "preAuthKeys": "预授权密钥", + "apiKeys": "API 密钥", + "policy": "策略", + "batchOperations": "批量操作", + "selectAll": "全选", + "deselectAll": "清空选择", + "selectedCount": "已选择 {count} 项", + "batchDelete": "删除所选", + "batchSetTags": "设置标签", + "batchDeleteConfirm": "确认删除所选节点?", + "batchDeleteWarning": "确定要删除 {count} 个节点吗?此操作无法撤销。", + "batchDeleted": "已删除 {count} 个节点", + "enterTags": "请输入标签,多个标签请用逗号分隔", + "tagsUpdated": "已更新 {count} 个节点的标签", + "backfillNodeIPs": "回填节点 IP", + "backfillNodeIPsDesc": "为尚未分配 Headscale 地址的节点补全 IP。", + "backfillConfirmDesc": "此操作只会补全缺失的 IP 地址,不会修改已有地址。请先确认下面的变更列表,再决定是否应用。", + "dryRun": "预览", + "applyChanges": "应用更改", + "backfillChanges": "待应用的更改", + "noChangesNeeded": "无需执行任何更改", + "backfillCompleted": "回填完成:已应用 {count} 项更改", + "enableAll": "全部启用", + "disableAll": "全部禁用", + "backToNodes": "返回节点列表", + "notFound": "未找到对应内容" + }, + "status": { + "title": "系统状态", + "healthCheck": "健康检查", + "monitorSystemHealth": "实时监控 Headscale 环境中关键组件的运行状态。", + "databaseConnectivity": "数据库连接", + "healthy": "正常", + "unhealthy": "异常", + "lastChecked": "最后检查时间", + "systemStatistics": "统计概览", + "totalUsers": "用户总数", + "totalNodes": "节点总数", + "onlineNodes": "在线节点", + "offlineNodes": "离线节点", + "totalRoutes": "路由总数", + "enabledRoutes": "已启用路由", + "totalPreAuthKeys": "预授权密钥总数", + "validPreAuthKeys": "有效预授权密钥", + "refreshing": "刷新中...", + "refresh": "刷新", + "autoRefresh": "每 30 秒自动刷新" + }, + "users": { + "title": "用户", + "createUser": "创建用户", + "displayName": "显示名称", + "provider": "身份提供方", + "email": "邮箱", + "nodes": "节点", + "preAuthKeys": "预授权密钥" + }, + "nodes": { + "title": "节点", + "createNode": "创建节点", + "registrationMethod": "注册方式", + "expiresAt": "到期时间", + "info": "详情" + }, + "routes": { + "title": "路由", + "enabled": "已启用", + "advertised": "已通告", + "destination": "目标网段" + }, + "acls": { + "title": "访问控制列表", + "config": "配置", + "groups": "用户组", + "hosts": "主机", + "policies": "策略", + "sshRules": "SSH 规则", + "tagOwners": "标签归属", + "hostCreated": "主机 “{name}” 已创建", + "tagCreated": "标签 “{name}” 已创建", + "sshRuleCreated": "SSH 规则 #{count} 已创建", + "policyCreated": "策略 #{count} 已创建", + "groupCreated": "用户组 “{name}” 已创建", + "configLoaded": "已从服务器加载 ACL 策略", + "configLoadFailed": "无法从服务器加载 ACL 策略", + "configSaved": "ACL 配置已保存", + "createHost": "创建主机", + "createTag": "创建标签", + "createSshRule": "创建 SSH 规则", + "createPolicy": "创建策略", + "createGroup": "创建用户组", + "saveConfig": "保存配置", + "loadConfig": "加载配置", + "editConfig": "编辑配置", + "applyConfig": "应用配置", + "cancelEditing": "取消编辑", + "resetConfig": "重置配置" + }, + "deploy": { + "title": "部署", + "copyCommand": "命令已复制到剪贴板", + "general": "常规设置", + "advertise": "通告设置", + "accept": "接收设置", + "saveDefaults": "保存默认设置", + "savedDefaults": "部署默认设置已保存", + "shieldsUp": "屏蔽入站连接", + "shieldsUpHelp": "阻止其他节点主动访问当前设备", + "generateQR": "生成二维码", + "generateQRHelp": "生成可供 Tailscale 客户端扫码导入的二维码", + "reset": "重置", + "resetHelp": "将未显式设置的参数恢复为默认值", + "operator": "运行用户", + "operatorHelp": "以其他本地用户身份运行客户端(仅限 Unix)", + "forceReauth": "强制重新认证", + "forceReauthHelp": "要求客户端重新向 Headscale 发起认证", + "sshServer": "SSH 服务", + "sshServerHelp": "在本机启用可由管理员访问的 SSH 服务", + "preAuthKey": "预授权密钥", + "preAuthKeyHelp": "为指定用户使用预授权密钥自动注册节点", + "unattended": "无人值守", + "unattendedHelp": "以无人值守模式运行 Tailscale 客户端,并在开机时自动启动", + "allowLANAccess": "允许访问局域网", + "allowLANAccessHelp": "在使用出口节点时,仍保留对本地局域网的访问能力", + "advertiseExitNode": "通告出口节点", + "advertiseExitNodeHelp": "允许其他 Tailnet 节点将当前设备作为出口网关使用", + "advertiseTags": "通告标签", + "advertiseTagsHelp": "在节点注册时附加这些通告标签", + "advertiseRoutes": "通告路由", + "advertiseRoutesHelp": "声明可通过当前节点访问的子网", + "acceptDNS": "接收 DNS 配置", + "acceptDNSHelp": "接受由 Headscale 下发的 DNS 配置", + "acceptRoutes": "接收路由", + "acceptRoutesHelp": "接受其他节点通告的子网路由", + "exitNode": "出口节点", + "exitNodeHelp": "将选中的节点作为出口节点使用", + "validKeys": "个可用密钥", + "tagError": "标签只能包含小写字母、数字、短横线或下划线", + "cidrError": "CIDR 格式无效" + }, + "home": { + "title": "首页", + "totalUsers": "用户总数", + "onlineUsers": "在线用户", + "validPreAuthKeys": "有效预授权密钥", + "totalNodes": "节点总数", + "onlineNodes": "在线节点", + "totalRoutes": "路由总数", + "clickToView": "点击查看详情" + }, + "cards": { + "autogroup": "自动组", + "provider": "身份提供方:", + "email": "邮箱:", + "displayName": "显示名称:", + "hostname": "主机名:", + "created": "创建时间:", + "lastSeen": "最后活跃:", + "user": "用户:", + "routes": "路由:", + "owner": "归属用户:", + "tags": "标签:", + "registerMethod": "注册方式:", + "expires": "到期时间:", + "name": "名称:", + "info": "信息:", + "ipv4Address": "IPv4 地址:", + "onlineNow": "当前在线", + "unspecified": "未指定", + "local": "本地", + "preAuthKey": "预授权密钥", + "cli": "命令行", + "oidc": "OIDC", + "custom": "自定义", + "group": "用户组", + "host": "主机", + "tag": "标签", + "srcObject": "源对象...", + "dstObject": "目标对象...", + "dstPorts": "目标端口...", + "selectOwners": "选择 {tagName} 的归属对象...", + "selectMembers": "选择 {groupName} 的成员...", + "invalidHost": "主机配置无效", + "invalidPort": "端口配置无效", + "protocol": "协议:", + "any": "任意", + "tcp": "TCP", + "udp": "UDP", + "icmp": "ICMP", + "sources": "来源:", + "destinations": "目标:", + "add": "添加", + "newOwner": "新的归属对象:", + "userNameEmpty": "用户名不能为空", + "nodeNameEmpty": "节点名称不能为空", + "sshRule": "SSH 规则", + "usernames": "用户名:", + "advertisedTags": "通告标签:", + "tagsPreventedByACL": "以下标签被当前 ACL 策略阻止:", + "hideInvalid": "隐藏无效项", + "create": "创建", + "ephemeral": "临时", + "reusable": "可重复使用", + "delete": "删除", + "hostRenameWarning": "主机 “{hostName}” 与某个用户名重复,请先为该主机重新命名。", + "deletedUser": "已删除用户 “{name}”(ID: {id})", + "deletedMachine": "已删除节点 “{name}”({id})", + "failedDeleteUser": "删除用户 “{name}”({id})失败", + "failedDeleteMachine": "删除节点 “{name}”({id})失败", + "stillHasNodes": " 该用户仍绑定节点。", + "invalidTags": "无效标签:", + "cannotRemoveAllTags": "无法移除已打标签节点的全部标签,至少需要保留一个标签。", + "tagsNotPermitted": "请求的标签未在 ACL 策略中定义,或当前策略不允许使用这些标签。", + "taggedToUserReauthRequired": "Headscale 0.28+ 不支持直接把已打标签的节点重新归属给用户。请在客户端执行 'tailscale up --advertise-tags= --force-reauth' 重新认证。", + "tagOwnershipWarning": "为节点添加标签后,设备会进入“标签身份(Tagged Persona)”模式。在该模式下,节点不再直接归属于某个用户,而是改由标签控制。对于 Headscale 0.28+,这种归属变化基本不可逆,除非清除标签并让设备重新认证。是否继续?", + "tagsMissingInACL": "以下标签在当前的 ACL 策略中未定义或不被允许: {tags}", + "autoCreateTagsPrompt": "是否自动在 ACL 策略中创建这些标签?", + "tagsCreatedInACL": "标签已成功在 ACL 策略中创建。", + "failedToCreateTags": "在 ACLs 中自动创建标签失败。", + "policyDeleted": "策略 #{number} 已删除", + "sshRuleDeleted": "SSH 规则 #{number} 已删除", + "groupDeleted": "用户组 “{name}” 已删除", + "tagDeleted": "标签 “{name}” 已删除", + "groupRenamedSuccess": "用户组已从 “{oldName}” 重命名为 “{newName}”", + "tagRenamedSuccess": "标签已从 “{oldName}” 重命名为 “{newName}”", + "membersOf": "成员", + "ownersOf": "归属对象", + "hostDeleted": "主机 “{name}” 已删除", + "nodes": "节点:", + "used": "已使用", + "expired": "已过期" + } +} diff --git a/src/lib/page/LanguageGate.svelte b/src/lib/page/LanguageGate.svelte new file mode 100644 index 0000000..929acb9 --- /dev/null +++ b/src/lib/page/LanguageGate.svelte @@ -0,0 +1,73 @@ + + +
+
+
+
+
+ Language Setup +
+ +
+

+ Choose your default language +
+ 选择默认界面语言 +

+

+ We did not find a saved language preference in your browser yet. Pick the language you want to use first, and you can still change it later in Settings. +

+

+ 当前浏览器中还没有保存语言偏好。请先选择默认界面语言,后续仍可在“设置”中随时切换。 +

+
+ +
+
+ The selected language will be saved locally in your browser. +
+
+ 所选语言会保存在当前浏览器中,后续访问将自动生效。 +
+
+
+ +
+ {#each LOCALE_OPTIONS as option} + + {/each} +
+
+
+
diff --git a/src/lib/page/PageDrawer.svelte b/src/lib/page/PageDrawer.svelte index b47e7c6..2b41c0c 100644 --- a/src/lib/page/PageDrawer.svelte +++ b/src/lib/page/PageDrawer.svelte @@ -5,12 +5,16 @@ import NodeInfo from '$lib/cards/node/NodeInfo.svelte'; import Navigation from '$lib/Navigation.svelte'; import { App } from '$lib/States.svelte'; + import { _ } from 'svelte-i18n'; const drawerStore = getDrawerStore(); - +
{#if $drawerStore?.id?.startsWith('userDrawer-')} u.id === $drawerStore?.meta.id)?.name ?? 'N/A'}> @@ -23,7 +27,7 @@ {/if} {#if $drawerStore?.id?.startsWith('navDrawer')} - + {/if} diff --git a/src/lib/page/PageHeader.svelte b/src/lib/page/PageHeader.svelte index 6f98cdd..13e13ca 100644 --- a/src/lib/page/PageHeader.svelte +++ b/src/lib/page/PageHeader.svelte @@ -7,6 +7,7 @@ import type { LayoutStyle, Valued } from '$lib/States.svelte'; import { App } from '$lib/States.svelte'; import type { Snippet } from 'svelte'; + import { _ } from 'svelte-i18n'; type PageHeaderProps = { filterString?: string, @@ -15,6 +16,7 @@ layout?: Valued, buttonText?: string, button?: Snippet, + children?: Snippet, } let { @@ -22,8 +24,9 @@ title, show = $bindable(false), layout = $bindable(undefined), - buttonText = 'Create', + buttonText = $_('common.create'), button, + children, }: PageHeaderProps = $props() const layoutCurrent = $derived(layout !== undefined ? layout.value : null) @@ -45,10 +48,9 @@
{title}
{#if layout && layoutCurrent} -
- +
+ App.toggleLayout(layout)} @@ -56,30 +58,39 @@ background="bg-secondary-500" size="sm" /> - +
{/if}
{#if button !== undefined} -
- {#if buttonText !== ""} - - {/if} - {#if filterString !== undefined} - - {/if} +
+
+ {#if buttonText !== ""} + + {/if} + {#if filterString !== undefined} +
+ +
+ {/if} +
+
+ {@render children?.()} +
{/if}
diff --git a/src/lib/parts/BatchOperationsBar.svelte b/src/lib/parts/BatchOperationsBar.svelte new file mode 100644 index 0000000..fc1def2 --- /dev/null +++ b/src/lib/parts/BatchOperationsBar.svelte @@ -0,0 +1,140 @@ + + +{#if selectedNodesArray.length > 0} +
+
+
+ + {$_('common.selectedCount', { values: { count: selectedNodesArray.length } })} + + +
+ + + + +
+ +
+
+ + +
+
+
+{/if} + + diff --git a/src/lib/parts/ExportModal.svelte b/src/lib/parts/ExportModal.svelte new file mode 100644 index 0000000..410a39a --- /dev/null +++ b/src/lib/parts/ExportModal.svelte @@ -0,0 +1,184 @@ + + +{#if show} + + +
{ + if (e.target === e.currentTarget) { + show = false; + onclose?.(); + } + }} + > +
e.stopPropagation()}> +
+

{$_('common.exportData')}

+ +
+ +
+
+ + +
+ +
+

{$_('common.exportResources')}

+
+ + + + +
+
+ +
+ + +
+
+ +
+ + +
+
+
+{/if} diff --git a/src/lib/parts/LoaderModal.svelte b/src/lib/parts/LoaderModal.svelte index 6958dc3..c649a9f 100644 --- a/src/lib/parts/LoaderModal.svelte +++ b/src/lib/parts/LoaderModal.svelte @@ -33,6 +33,8 @@
{title}
{body}