diff --git a/.gitignore b/.gitignore index fc18f83..b036f1a 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ build/ /.cache/ ovpn-connector.json /webui/src/json-rpc.js +app/src/main/resources/htdocs/ +*.pfapp diff --git a/webui/index.html b/webui/index.html index 19729ae..5cac928 100644 --- a/webui/index.html +++ b/webui/index.html @@ -2,9 +2,9 @@ - + - SDN Control + pfSDN
diff --git a/webui/package-lock.json b/webui/package-lock.json index 1c75aca..93fadc7 100644 --- a/webui/package-lock.json +++ b/webui/package-lock.json @@ -11,474 +11,13 @@ "jquery": "^3.7.1" }, "devDependencies": { - "@vitejs/plugin-vue": "^6.0.1", "sass": "^1.93.2", - "vite": "^7.1.7", - "vite-plugin-vue-devtools": "^8.0.2" + "vite": "^7.1.7" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", - "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.4", - "@babel/types": "^7.28.4", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.3.tgz", - "integrity": "sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz", - "integrity": "sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", - "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.27.1", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.4" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", - "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-decorators": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", - "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.0.tgz", - "integrity": "sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.10", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", @@ -921,56 +460,6 @@ "node": ">=18" } }, - "node_modules/@jridgewell/gen-mapping": { - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@parcel/watcher": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", @@ -1281,20 +770,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@polka/url": { - "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" - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.29", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.29.tgz", - "integrity": "sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.52.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.3.tgz", @@ -1603,26 +1078,6 @@ "win32" ] }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1630,282 +1085,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@vitejs/plugin-vue": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.1.tgz", - "integrity": "sha512-+MaE752hU0wfPFJEUAIxqw18+20euHHdxVtMvbFcOEpjEyfqXH/5DCoTHiVJ0J29EhTJdoTkjEv5YBKU9dnoTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "1.0.0-beta.29" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/babel-helper-vue-transform-on": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", - "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/babel-plugin-jsx": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", - "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.2", - "@vue/babel-helper-vue-transform-on": "1.5.0", - "@vue/babel-plugin-resolve-type": "1.5.0", - "@vue/shared": "^3.5.18" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - } - } - }, - "node_modules/@vue/babel-plugin-resolve-type": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", - "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/parser": "^7.28.0", - "@vue/compiler-sfc": "^3.5.18" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz", - "integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.4", - "@vue/shared": "3.5.22", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz", - "integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.22", - "@vue/shared": "3.5.22" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz", - "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.4", - "@vue/compiler-core": "3.5.22", - "@vue/compiler-dom": "3.5.22", - "@vue/compiler-ssr": "3.5.22", - "@vue/shared": "3.5.22", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.19", - "postcss": "^8.5.6", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz", - "integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.22", - "@vue/shared": "3.5.22" - } - }, - "node_modules/@vue/devtools-core": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.0.2.tgz", - "integrity": "sha512-V7eKTTHoS6KfK8PSGMLZMhGv/9yNDrmv6Qc3r71QILulnzPnqK2frsTyx3e2MrhdUZnENPEm6hcb4z0GZOqNhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-kit": "^8.0.2", - "@vue/devtools-shared": "^8.0.2", - "mitt": "^3.0.1", - "nanoid": "^5.1.5", - "pathe": "^2.0.3", - "vite-hot-client": "^2.1.0" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, - "node_modules/@vue/devtools-core/node_modules/nanoid": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", - "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/@vue/devtools-kit": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.2.tgz", - "integrity": "sha512-yjZKdEmhJzQqbOh4KFBfTOQjDPMrjjBNCnHBvnTGJX+YLAqoUtY2J+cg7BE+EA8KUv8LprECq04ts75wCoIGWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-shared": "^8.0.2", - "birpc": "^2.5.0", - "hookable": "^5.5.3", - "mitt": "^3.0.1", - "perfect-debounce": "^2.0.0", - "speakingurl": "^14.0.1", - "superjson": "^2.2.2" - } - }, - "node_modules/@vue/devtools-shared": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.2.tgz", - "integrity": "sha512-mLU0QVdy5Lp40PMGSixDw/Kbd6v5dkQXltd2r+mdVQV7iUog2NlZuLxFZApFZ/mObUBDhoCpf0T3zF2FWWdeHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "rfdc": "^1.4.1" - } - }, - "node_modules/@vue/reactivity": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.22.tgz", - "integrity": "sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/shared": "3.5.22" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.22.tgz", - "integrity": "sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/reactivity": "3.5.22", - "@vue/shared": "3.5.22" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.22.tgz", - "integrity": "sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/reactivity": "3.5.22", - "@vue/runtime-core": "3.5.22", - "@vue/shared": "3.5.22", - "csstype": "^3.1.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.22.tgz", - "integrity": "sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/compiler-ssr": "3.5.22", - "@vue/shared": "3.5.22" - }, - "peerDependencies": { - "vue": "3.5.22" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz", - "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==", - "dev": true, - "license": "MIT" - }, - "node_modules/ansis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", - "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.9.tgz", - "integrity": "sha512-hY/u2lxLrbecMEWSB0IpGzGyDyeoMFQhCvZd2jGFSE5I17Fh01sYUBPCJtkWERw7zrac9+cIghxm/ytJa2X8iA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/birpc": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz", - "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", @@ -1920,77 +1099,6 @@ "node": ">=8" } }, - "node_modules/browserslist": { - "version": "4.26.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", - "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.8.3", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bundle-name": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", - "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "run-applescript": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001745", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001745.tgz", - "integrity": "sha512-ywt6i8FzvdgrrrGbr1jZVObnVv6adj+0if2/omv9cmR2oiZs30zL4DIyaptKcbOrBdOIc74QTMoJvSE2QHh5UQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -2007,113 +1115,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/copy-anything": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", - "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-what": "^4.1.8" - }, - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/default-browser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", - "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", - "dev": true, - "license": "MIT", - "dependencies": { - "bundle-name": "^4.1.0", - "default-browser-id": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", - "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -2128,36 +1129,6 @@ "node": ">=0.10" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.227", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.227.tgz", - "integrity": "sha512-ITxuoPfJu3lsNWUi2lBM2PaBPYgH3uqmxut5vmBxgYvyI4AlJ6P3Cai1O76mOrkJCBzq0IxWg/NtqOrpu/0gKA==", - "dev": true, - "license": "ISC" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-stack-parser-es": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", - "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, "node_modules/esbuild": { "version": "0.25.10", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", @@ -2200,66 +1171,6 @@ "@esbuild/win32-x64": "0.25.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, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/estree-walker": { - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/execa": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.0.tgz", - "integrity": "sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.6", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.1", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.2.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -2289,50 +1200,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hookable": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", - "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/human-signals": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.1.tgz", - "integrity": "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, "node_modules/immutable": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", @@ -2340,22 +1207,6 @@ "dev": true, "license": "MIT" }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2381,25 +1232,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2411,147 +1243,12 @@ "node": ">=0.12.0" } }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-what": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", - "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.13" - }, - "funding": { - "url": "https://github.com/sponsors/mesqueeb" - } - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, "node_modules/jquery": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", "license": "MIT" }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.19", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", - "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -2567,30 +1264,6 @@ "node": ">=8.6" } }, - "node_modules/mitt": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", - "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", - "dev": true, - "license": "MIT" - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -2618,106 +1291,6 @@ "license": "MIT", "optional": true }, - "node_modules/node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", - "dev": true, - "license": "MIT" - }, - "node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/open": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", - "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "default-browser": "^5.2.1", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "wsl-utils": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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/perfect-debounce": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", - "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", - "dev": true, - "license": "MIT" - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2768,22 +1341,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/pretty-ms": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", - "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -2798,13 +1355,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, "node_modules/rollup": { "version": "4.52.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.3.tgz", @@ -2847,19 +1397,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/run-applescript": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", - "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/sass": { "version": "1.93.2", "resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz", @@ -2881,67 +1418,6 @@ "@parcel/watcher": "^2.4.1" } }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sirv": { - "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": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2952,42 +1428,6 @@ "node": ">=0.10.0" } }, - "node_modules/speakingurl": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", - "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superjson": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz", - "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "copy-anything": "^3.0.2" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -3050,90 +1490,6 @@ "node": ">=8.0" } }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unplugin-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.0.tgz", - "integrity": "sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "pathe": "^2.0.3", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=20.19.0" - }, - "funding": { - "url": "https://github.com/sponsors/sxzz" - } - }, - "node_modules/unplugin-utils/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, "node_modules/vite": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz", @@ -3209,111 +1565,6 @@ } } }, - "node_modules/vite-dev-rpc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz", - "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==", - "dev": true, - "license": "MIT", - "dependencies": { - "birpc": "^2.4.0", - "vite-hot-client": "^2.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" - } - }, - "node_modules/vite-hot-client": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", - "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" - } - }, - "node_modules/vite-plugin-inspect": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz", - "integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansis": "^4.1.0", - "debug": "^4.4.1", - "error-stack-parser-es": "^1.0.5", - "ohash": "^2.0.11", - "open": "^10.2.0", - "perfect-debounce": "^2.0.0", - "sirv": "^3.0.1", - "unplugin-utils": "^0.3.0", - "vite-dev-rpc": "^1.1.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - }, - "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "@nuxt/kit": { - "optional": true - } - } - }, - "node_modules/vite-plugin-vue-devtools": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.0.2.tgz", - "integrity": "sha512-1069qvMBcyAu3yXQlvYrkwoyLOk0lSSR/gTKy/vy+Det7TXnouGei6ZcKwr5TIe938v/14oLlp0ow6FSJkkORA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/devtools-core": "^8.0.2", - "@vue/devtools-kit": "^8.0.2", - "@vue/devtools-shared": "^8.0.2", - "execa": "^9.6.0", - "sirv": "^3.0.2", - "vite-plugin-inspect": "^11.3.3", - "vite-plugin-vue-inspector": "^5.3.2" - }, - "engines": { - "node": ">=v14.21.3" - }, - "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0-0" - } - }, - "node_modules/vite-plugin-vue-inspector": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", - "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.23.0", - "@babel/plugin-proposal-decorators": "^7.23.0", - "@babel/plugin-syntax-import-attributes": "^7.22.5", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-transform-typescript": "^7.22.15", - "@vue/babel-plugin-jsx": "^1.1.5", - "@vue/compiler-dom": "^3.3.4", - "kolorist": "^1.8.0", - "magic-string": "^0.30.4" - }, - "peerDependencies": { - "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" - } - }, "node_modules/vite/node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -3344,81 +1595,6 @@ "funding": { "url": "https://github.com/sponsors/jonschlinkert" } - }, - "node_modules/vue": { - "version": "3.5.22", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz", - "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/compiler-dom": "3.5.22", - "@vue/compiler-sfc": "3.5.22", - "@vue/runtime-dom": "3.5.22", - "@vue/server-renderer": "3.5.22", - "@vue/shared": "3.5.22" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wsl-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", - "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-wsl": "^3.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/webui/public/favicon.ico b/webui/public/favicon.ico deleted file mode 100644 index df36fcf..0000000 Binary files a/webui/public/favicon.ico and /dev/null differ diff --git a/webui/public/favicon.png b/webui/public/favicon.png new file mode 100644 index 0000000..436673d Binary files /dev/null and b/webui/public/favicon.png differ diff --git a/webui/public/icon100.png b/webui/public/icon100.png new file mode 100644 index 0000000..e9d1e3d Binary files /dev/null and b/webui/public/icon100.png differ diff --git a/webui/src/main.js b/webui/src/main.js index 4dbf994..fd2c790 100644 --- a/webui/src/main.js +++ b/webui/src/main.js @@ -8,7 +8,7 @@ window.$ = window.jQuery = $; import { JSONRPC } from '@/json-rpc.js'; // 🔥 Указываем URL сервера, как ты и сделал -JSONRPC.url = "http://localhost:8080" + JSONRPC.url; +//JSONRPC.url = "http://localhost:8080" + JSONRPC.url; // 2. Импорт главного модуля приложения import { initApp } from './modules/app.js'; diff --git a/webui/src/modules/router.js b/webui/src/modules/router.js index 1d90d1f..4944f55 100644 --- a/webui/src/modules/router.js +++ b/webui/src/modules/router.js @@ -7,6 +7,10 @@ import { Components } from '../pages/Components.js'; import { APITokens } from '../pages/APITokens.js'; import { getEnabledComponents } from './app.js'; import { OVPNConfig } from '../pages/OVPN.js'; +import { TDNSConfig } from '../pages/TDNS.js'; +import { FRRConfig } from '../pages/FRR.js'; +import { SettingsPage } from '../pages/Settings.js'; +import { LogsPage } from '../pages/Logs.js'; // Переменная для отслеживания текущего активного хеша (для корректного unmount) @@ -21,6 +25,9 @@ const allMenuItems = [ { label: 'Компоненты', path: 'components', component: null }, { label: 'API', path: 'api', component: null }, { label: 'Настройка OVPN', path: 'ovpn', component: 'ru.kirillius.pf.sdn.External.API.Components.OVPN' }, + { label: 'Настройка TDNS', path: 'tdns', component: 'ru.kirillius.pf.sdn.External.API.Components.TDNS' }, + { label: 'Настройка FRR', path: 'frr', component: 'ru.kirillius.pf.sdn.External.API.Components.FRR' }, + { label: 'Журнал', path: 'logs', component: null }, ]; // 2. Определение страниц @@ -36,9 +43,9 @@ const routes = { unmount: Subscriptions.unmount }, '#settings': { - render: () => '

Системные Настройки

Конфигурация сети, пользователя и безопасности.

', - mount: () => {}, - unmount: () => {} + render: SettingsPage.render, + mount: SettingsPage.mount, + unmount: SettingsPage.unmount }, '#components': { render: Components.render, @@ -54,6 +61,21 @@ const routes = { render: OVPNConfig.render, mount: OVPNConfig.mount, unmount: OVPNConfig.unmount + }, + '#tdns': { + render: TDNSConfig.render, + mount: TDNSConfig.mount, + unmount: TDNSConfig.unmount + }, + '#frr': { + render: FRRConfig.render, + mount: FRRConfig.mount, + unmount: FRRConfig.unmount + }, + '#logs': { + render: LogsPage.render, + mount: LogsPage.mount, + unmount: LogsPage.unmount } }; diff --git a/webui/src/modules/ui.js b/webui/src/modules/ui.js index f965f0a..5feb69c 100644 --- a/webui/src/modules/ui.js +++ b/webui/src/modules/ui.js @@ -2,6 +2,9 @@ import $ from 'jquery'; import { handleLogin, handleLogout } from './auth.js'; import { setAuthenticated } from './app.js'; import { renderPage, getFilteredMenuItems } from './router.js'; +import { JSONRPC } from '@/json-rpc.js'; + +let configIndicatorInterval = null; // Функция рендеринга формы авторизации @@ -10,14 +13,11 @@ export function renderLoginForm() {

Авторизация

- +
+
-
@@ -63,18 +63,52 @@ export function renderLoginForm() { // Функция рендеринга рабочего стола (Dashboard) -export function renderDashboard() { +async function fetchConfigChanged() { + try { + return await JSONRPC.System.isConfigChanged(); + } catch (error) { + console.error('Ошибка при проверке изменения конфигурации:', error); + return false; + } +} + +async function updateStatisticsIndicator() { + const hasChanges = await fetchConfigChanged(); + const $statsLink = $('#main-nav .menu-item[data-path="stats"]'); + if (!$statsLink.length) { + return; + } + + const $indicator = $statsLink.find('.menu-indicator'); + if (hasChanges) { + if (!$indicator.length) { + $statsLink.append(''); + } + } else { + $indicator.remove(); + } +} + +export async function renderDashboard() { // Используем функцию из роутера для получения актуального списка меню const menuItems = getFilteredMenuItems(); + const configChanged = await fetchConfigChanged(); const sidebarHtml = menuItems.map(item => { - return `${item.label}`; + const isStatistics = item.path === 'stats'; + const indicator = isStatistics && configChanged + ? '' + : ''; + return `${item.label}${indicator}`; }).join(''); const html = `
`); @@ -165,13 +190,14 @@ function collectConfigFromForm() { username: $(SELECTORS.username).val(), password: newPassword ? newPassword : (shellConfig.password || ''), }, - restartCommand: $(SELECTORS.restartCommand).val() + restartCommand: $(SELECTORS.restartCommand).val(), + restartOnUpdate: $(SELECTORS.restartOnUpdate).prop('checked') }; } async function handleSave() { const $button = $(SELECTORS.saveButton); - await runAction($button, 'Сохранение...', async () => { + await runAction($button, 'Применение...', async () => { const newConfig = collectConfigFromForm(); await JSONRPC.System.setComponentConfig(OVPN_COMPONENT_NAME, newConfig); currentConfig = newConfig; @@ -208,10 +234,12 @@ function detachEventHandlers() { function toggleSSHFields() { const enabled = $(SELECTORS.useSSH).prop('checked'); + const $shellFields = $(SELECTORS.container).find(`.${CLASS_NAMES.shellFields}`); $(SELECTORS.host).prop('disabled', !enabled); $(SELECTORS.port).prop('disabled', !enabled); $(SELECTORS.username).prop('disabled', !enabled); $(SELECTORS.password).prop('disabled', !enabled); + $shellFields.toggle(enabled); } export const OVPNConfig = { diff --git a/webui/src/pages/Settings.js b/webui/src/pages/Settings.js new file mode 100644 index 0000000..eaf2358 --- /dev/null +++ b/webui/src/pages/Settings.js @@ -0,0 +1,494 @@ +import $ from 'jquery'; +import { JSONRPC } from '@/json-rpc.js'; + +const FIELD_IDS = { + container: 'settings-config-container', + status: 'settings-status-message', + saveButton: 'save-settings-btn', + changePasswordButton: 'settings-change-password-btn', + updateSubscriptionsInterval: 'settings-update-subscriptions-interval', + cachingAS: 'settings-caching-as', + updateASInterval: 'settings-update-as-interval', + host: 'settings-host', + cacheDirectory: 'settings-cache-directory', + httpPort: 'settings-http-port', + mergeSubnets: 'settings-merge-subnets', + displayDebuggingInfo: 'settings-display-debugging-info', + mergeSubnetsWithUsage: 'settings-merge-subnets-with-usage', + subscriptionsList: 'settings-subscriptions-list', + addSubscriptionButton: 'settings-add-subscription', + customASN: 'settings-custom-asn', + customSubnets: 'settings-custom-subnets', + customDomains: 'settings-custom-domains', + filteredASN: 'settings-filtered-asn', + filteredSubnets: 'settings-filtered-subnets', + filteredDomains: 'settings-filtered-domains' +}; + +const CLASS_NAMES = { + subscriptionEntry: 'settings-subscription-entry', + subscriptionRemove: 'settings-subscription-remove', + subscriptionName: 'settings-subscription-name', + subscriptionType: 'settings-subscription-type', + subscriptionSource: 'settings-subscription-source' +}; + +let currentConfig = {}; +let repositoryTypes = []; +let statusTimeoutId = null; + +const getStatusElement = () => $(`#${FIELD_IDS.status}`); + +function clearStatus() { + const $status = getStatusElement(); + if (!$status.length) { + return; + } + if (statusTimeoutId) { + clearTimeout(statusTimeoutId); + statusTimeoutId = null; + } + $status.stop(true, true).hide().text('').removeClass('success-message error-message'); +} + +function updateStatus(message, type) { + const $status = getStatusElement(); + if (!$status.length) { + return; + } + if (statusTimeoutId) { + clearTimeout(statusTimeoutId); + } + $status + .removeClass('success-message error-message') + .addClass(type === 'success' ? 'success-message' : 'error-message') + .text(message) + .show(); + + statusTimeoutId = window.setTimeout(() => { + $status.fadeOut(); + }, 5000); +} + +async function runAction($button, pendingText, action, messages) { + if (!$button.length) { + return; + } + + const originalText = $button.text(); + $button.prop('disabled', true).text(pendingText); + clearStatus(); + + try { + const result = await action(); + if (messages?.success) { + const successMessage = typeof messages.success === 'function' ? messages.success(result) : messages.success; + if (successMessage) { + updateStatus(successMessage, 'success'); + } + } + } catch (error) { + console.error(messages?.log || 'Ошибка при выполнении действия Settings:', error); + if (messages?.error) { + updateStatus(messages.error, 'error'); + } + } finally { + $button.prop('disabled', false).text(originalText); + } +} + +async function loadSettings() { + try { + const [config, repoTypes] = await Promise.all([ + JSONRPC.System.getConfig(), + JSONRPC.System.getRepositoryTypes() + ]); + currentConfig = config || {}; + repositoryTypes = Array.isArray(repoTypes) ? repoTypes : []; + return true; + } catch (error) { + console.error('Ошибка загрузки настроек:', error); + currentConfig = {}; + repositoryTypes = []; + return false; + } +} + +function getConfigValue(key, fallback) { + return key in currentConfig ? currentConfig[key] : fallback; +} + +function getTypeValue(type) { + if (!type) { + return ''; + } + return typeof type === 'string' ? type : type?.name || ''; +} + +function getTypeLabel(value) { + if (!value) { + return ''; + } + const parts = value.split('.'); + return parts.length ? parts[parts.length - 1] : value; +} + +function renderRepositoryOptions(selected) { + const options = repositoryTypes.map(type => { + const value = getTypeValue(type); + if (!value) { + return ''; + } + const isSelected = value === selected ? 'selected' : ''; + const label = getTypeLabel(value); + return ``; + }).join(''); + + return `${options}`; +} + +function createSubscriptionRow(subscription = {}, index = 0) { + const name = subscription.name || ''; + const type = subscription.type || ''; + const source = subscription.source || ''; + const uid = `${Date.now()}-${index}`; + + return ` +
+
+

Репозиторий

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ `; +} + +function populateSubscriptions() { + const $list = $(`#${FIELD_IDS.subscriptionsList}`); + $list.empty(); + const subscriptions = Array.isArray(currentConfig.subscriptions) ? currentConfig.subscriptions : []; + subscriptions.forEach((subscription, index) => { + $list.append(createSubscriptionRow(subscription, index)); + }); +} + +function textareaFromArray(array) { + if (!Array.isArray(array) || !array.length) { + return ''; + } + return array.join('\n'); +} + +function renderSettingsForm() { + const $container = $(`#${FIELD_IDS.container}`); + const updateSubscriptionsInterval = getConfigValue('updateSubscriptionsInterval', 1); + const cachingAS = !!getConfigValue('cachingAS', false); + const updateASInterval = getConfigValue('updateASInterval', 1); + const host = getConfigValue('host', ''); + const cacheDirectory = getConfigValue('cacheDirectory', ''); + const httpPort = getConfigValue('httpPort', 8080); + const mergeSubnets = !!getConfigValue('mergeSubnets', false); + const displayDebuggingInfo = !!getConfigValue('displayDebuggingInfo', false); + const mergeSubnetsWithUsage = getConfigValue('mergeSubnetsWithUsage', 80); + + const customResources = getConfigValue('customResources', {}); + const filteredResources = getConfigValue('filteredResources', {}); + + $container.html(` +
+
+ +
+

Обновление ресурсов

+
+ + +
+
+ + +
+
+ + +
+ +

Сервис

+

После изменения параметров сервиса необходимо перезапустить сервис на вкладке «Статистика», чтобы настройки вступили в силу.

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +

Сетевые ресурсы

+
+ + +
+
+ + +
+
+

Дополнительные ресурсы

+
+ + +
+
+ + +
+
+ + +
+
+
+

Фильтр ресурсов

+
+ + +
+
+ + +
+
+ + +
+
+ +

Репозитории подписок

+
+ + +
+ +
+ +
+ `); + + populateSubscriptions(); + attachEventHandlers(); +} + +function addSubscriptionRow(subscription = {}) { + const $list = $(`#${FIELD_IDS.subscriptionsList}`); + const index = $list.children(`.${CLASS_NAMES.subscriptionEntry}`).length; + $list.append(createSubscriptionRow(subscription, index)); +} + +function parseNumberInRange(value, min, max, fieldName) { + const num = parseInt(value, 10); + if (Number.isNaN(num) || num < min || num > max) { + throw new Error(`${fieldName} должно быть числом от ${min} до ${max}.`); + } + return num; +} + +function parseTextAreaLines($element, transform) { + const lines = $element.val().split('\n').map(line => line.trim()).filter(Boolean); + if (transform) { + return lines.map(value => transform(value)); + } + return lines; +} + +function parseASNLines($element) { + const lines = $element.val().split('\n').map(line => line.trim()).filter(Boolean); + return lines.map(value => { + const num = parseInt(value, 10); + if (Number.isNaN(num) || num < 0) { + throw new Error(`Некорректный ASN: ${value}`); + } + return num; + }); +} + +function collectSubscriptions() { + const subscriptions = []; + let hasEmptyType = false; + $(`#${FIELD_IDS.subscriptionsList}`).find(`.${CLASS_NAMES.subscriptionEntry}`).each((_, element) => { + const $entry = $(element); + const name = $entry.find(`.${CLASS_NAMES.subscriptionName}`).val().trim(); + const type = $entry.find(`.${CLASS_NAMES.subscriptionType}`).val(); + const source = $entry.find(`.${CLASS_NAMES.subscriptionSource}`).val().trim(); + + if (!type) { + hasEmptyType = true; + return false; + } + + if (name || type || source) { + subscriptions.push({ name, type, source }); + } + return true; + }); + + if (hasEmptyType) { + throw new Error('Для каждого репозитория необходимо выбрать тип.'); + } + + return subscriptions; +} + +function buildNetworkResourceBundle({ asnSelector, subnetsSelector, domainsSelector }) { + const $asn = $(`#${asnSelector}`); + const $subnets = $(`#${subnetsSelector}`); + const $domains = $(`#${domainsSelector}`); + + return { + ASN: parseASNLines($asn), + subnets: parseTextAreaLines($subnets), + domains: parseTextAreaLines($domains) + }; +} + +function collectSettingsFromForm() { + const updateSubscriptionsInterval = parseNumberInRange($(`#${FIELD_IDS.updateSubscriptionsInterval}`).val(), 1, 24, 'Интервал обновления подписок'); + const updateASInterval = parseNumberInRange($(`#${FIELD_IDS.updateASInterval}`).val(), 1, 24, 'Интервал обновления ASN'); + const mergeSubnetsWithUsage = parseNumberInRange($(`#${FIELD_IDS.mergeSubnetsWithUsage}`).val(), 51, 99, 'Процент объединения подсетей'); + + const httpPortValue = parseInt($(`#${FIELD_IDS.httpPort}`).val(), 10); + if (Number.isNaN(httpPortValue) || httpPortValue < 1 || httpPortValue > 65535) { + throw new Error('HTTP порт должен быть от 1 до 65535.'); + } + + const subscriptions = collectSubscriptions(); + const customResources = buildNetworkResourceBundle({ + asnSelector: FIELD_IDS.customASN, + subnetsSelector: FIELD_IDS.customSubnets, + domainsSelector: FIELD_IDS.customDomains + }); + const filteredResources = buildNetworkResourceBundle({ + asnSelector: FIELD_IDS.filteredASN, + subnetsSelector: FIELD_IDS.filteredSubnets, + domainsSelector: FIELD_IDS.filteredDomains + }); + + return { + ...currentConfig, + updateSubscriptionsInterval, + cachingAS: $(`#${FIELD_IDS.cachingAS}`).prop('checked'), + updateASInterval, + host: $(`#${FIELD_IDS.host}`).val().trim(), + cacheDirectory: $(`#${FIELD_IDS.cacheDirectory}`).val().trim(), + httpPort: httpPortValue, + mergeSubnets: $(`#${FIELD_IDS.mergeSubnets}`).prop('checked'), + displayDebuggingInfo: $(`#${FIELD_IDS.displayDebuggingInfo}`).prop('checked'), + mergeSubnetsWithUsage, + subscriptions, + customResources, + filteredResources + }; +} + +async function handleSave() { + const $button = $(`#${FIELD_IDS.saveButton}`); + + let newConfig; + try { + newConfig = collectSettingsFromForm(); + } catch (error) { + updateStatus(error.message || 'Ошибка подготовки настроек.', 'error'); + return; + } + + await runAction($button, 'Применение...', async () => { + await JSONRPC.System.setConfig(newConfig); + currentConfig = newConfig; + }, { + success: 'Настройки успешно сохранены.', + error: 'Ошибка при сохранении настроек.', + log: 'Ошибка сохранения настроек' + }); +} + +async function handleChangePassword() { + const newPassword = prompt('Введите новый пароль администратора:'); + if (newPassword === null) { + return; + } + if (!newPassword.trim()) { + updateStatus('Пароль не может быть пустым.', 'error'); + return; + } + + const $button = $(`#${FIELD_IDS.changePasswordButton}`); + await runAction($button, 'Сохранение...', async () => { + await JSONRPC.Auth.changePassword(newPassword.trim()); + }, { + success: 'Пароль успешно изменён.', + error: 'Ошибка при смене пароля.', + log: 'Ошибка смены пароля' + }); +} + +function attachEventHandlers() { + $(`#${FIELD_IDS.saveButton}`).off('click').on('click', handleSave); + $(`#${FIELD_IDS.addSubscriptionButton}`).off('click').on('click', () => addSubscriptionRow()); + $(`#${FIELD_IDS.subscriptionsList}`).off('click', `.${CLASS_NAMES.subscriptionRemove}`).on('click', `.${CLASS_NAMES.subscriptionRemove}`, function (event) { + event.preventDefault(); + $(this).closest(`.${CLASS_NAMES.subscriptionEntry}`).remove(); + }); + $(`#${FIELD_IDS.changePasswordButton}`).off('click').on('click', handleChangePassword); +} + +function detachEventHandlers() { + $(`#${FIELD_IDS.saveButton}`).off('click'); + $(`#${FIELD_IDS.addSubscriptionButton}`).off('click'); + $(`#${FIELD_IDS.subscriptionsList}`).off('click', `.${CLASS_NAMES.subscriptionRemove}`); + $(`#${FIELD_IDS.changePasswordButton}`).off('click'); +} + +export const SettingsPage = { + render: () => ` +

Системные Настройки

+
+

Загрузка настроек...

+
+ `, + mount: async () => { + const success = await loadSettings(); + if (success) { + renderSettingsForm(); + } else { + $(`#${FIELD_IDS.container}`).html('

Не удалось загрузить настройки.

'); + } + }, + unmount: () => { + detachEventHandlers(); + clearStatus(); + currentConfig = {}; + repositoryTypes = []; + } +}; diff --git a/webui/src/pages/Statistics.js b/webui/src/pages/Statistics.js index 3604b78..188da40 100644 --- a/webui/src/pages/Statistics.js +++ b/webui/src/pages/Statistics.js @@ -3,10 +3,11 @@ import { JSONRPC } from '@/json-rpc.js'; const POLLING_INTERVAL = 5000; let updateInterval = null; +let configChanged = false; const $content = () => $('#statistics-content'); -const createStatusCard = (title, status, buttons = [], resourceStatsHtml = '', customStatusContent = null) => { +const createStatusCard = (title, status, buttons = [], resourceStatsHtml = '', customStatusContent = null, extraClass = '') => { const warningStatuses = ['Обновляется', 'Обнаружено', 'Готово к установке']; const statusClass = warningStatuses.includes(status) ? 'text-yellow-500' : 'text-green-500'; const statusSection = customStatusContent || ` @@ -23,7 +24,7 @@ const createStatusCard = (title, status, buttons = [], resourceStatsHtml = '', c : ''; return ` -
+

${title}

${statusSection} ${buttonsHtml} @@ -85,7 +86,7 @@ async function renderSystemAndManagerStatus() { const availableVersion = (versionInfo && versionInfo.available) || ''; const currentVersion = (versionInfo && versionInfo.current) || ''; const downloadedVersion = (versionInfo && versionInfo.downloaded) || ''; - const isConfigChanged = await JSONRPC.System.isConfigChanged(); + configChanged = await JSONRPC.System.isConfigChanged(); const hasAvailableUpdate = availableVersion && availableVersion !== currentVersion; const isDownloaded = hasAvailableUpdate && downloadedVersion === availableVersion; const updateButtonDisabled = !hasAvailableUpdate || isDownloaded; @@ -103,8 +104,8 @@ async function renderSystemAndManagerStatus() { Текущая версия: ${currentVersion || '-'}
Последняя версия: ${availableVersion || '-'}
-

- Конфигурация: ${isConfigChanged ? 'изменена' : 'актуальна'} +

+ Конфигурация: ${configChanged ? 'изменена' : 'актуальна'}

`; const isSubUpdating = await JSONRPC.SubscriptionManager.isUpdating(); @@ -128,13 +129,14 @@ async function renderSystemAndManagerStatus() { }, { id: 'save-config-btn', - label: 'Сохранить', - disabled: !isConfigChanged, + label: 'Сохранить настройки', + disabled: !configChanged, loadingLabel: 'Сохранение...' } ], '', - versionStatusHtml + versionStatusHtml, + configChanged ? 'stat-card-highlight' : '' )); const subStatsHtml = `
@@ -263,7 +265,7 @@ function attachEventHandlers() { await renderSystemAndManagerStatus(); } catch (e) { alert('Ошибка при сохранении конфигурации!'); - $btn.prop('disabled', false).text('Сохранить'); + $btn.prop('disabled', false).text('Сохранить настройки'); } }); } diff --git a/webui/src/pages/TDNS.js b/webui/src/pages/TDNS.js new file mode 100644 index 0000000..49e9aba --- /dev/null +++ b/webui/src/pages/TDNS.js @@ -0,0 +1,262 @@ +import $ from 'jquery'; +import { JSONRPC } from '@/json-rpc.js'; + +const TDNS_COMPONENT_NAME = 'ru.kirillius.pf.sdn.External.API.Components.TDNS'; + +const FIELD_IDS = { + container: 'tdns-config-container', + instancesList: 'tdns-instances-list', + addInstanceButton: 'tdns-add-instance-btn', + saveButton: 'save-tdns-btn', + status: 'tdns-status-message' +}; + +const CLASS_NAMES = { + instance: 'tdns-instance-entry', + removeButton: 'tdns-remove-instance-btn', + serverInput: 'tdns-server-input', + tokenInput: 'tdns-token-input', + forwarderInput: 'tdns-forwarder-input' +}; + +const SELECTORS = { + container: `#${FIELD_IDS.container}`, + instancesList: `#${FIELD_IDS.instancesList}`, + addInstanceButton: `#${FIELD_IDS.addInstanceButton}`, + saveButton: `#${FIELD_IDS.saveButton}`, + status: `#${FIELD_IDS.status}` +}; + +let currentConfig = { instances: [] }; +let statusTimeoutId = null; +let instanceCounter = 0; + +const getStatusElement = () => $(SELECTORS.status); + +function normalizeConfig(config) { + if (!config || !Array.isArray(config.instances)) { + return { instances: [] }; + } + return { + instances: config.instances.map(instance => ({ + server: instance?.server || '', + token: instance?.token || '', + forwarder: instance?.forwarder || '' + })) + }; +} + +function clearStatus() { + const $status = getStatusElement(); + if (!$status.length) { + return; + } + if (statusTimeoutId) { + clearTimeout(statusTimeoutId); + statusTimeoutId = null; + } + $status.stop(true, true).hide().text('').removeClass('success-message error-message'); +} + +function updateStatus(message, type) { + const $status = getStatusElement(); + if (!$status.length) { + return; + } + if (statusTimeoutId) { + clearTimeout(statusTimeoutId); + } + $status + .removeClass('success-message error-message') + .addClass(type === 'success' ? 'success-message' : 'error-message') + .text(message) + .show(); + + statusTimeoutId = window.setTimeout(() => { + $status.fadeOut(); + }, 5000); +} + +async function runAction($button, pendingText, action, messages) { + if (!$button.length) { + return; + } + + const originalText = $button.text(); + $button.prop('disabled', true).text(pendingText); + clearStatus(); + + try { + const result = await action(); + if (messages?.success) { + const successMessage = typeof messages.success === 'function' + ? messages.success(result) + : messages.success; + if (successMessage) { + updateStatus(successMessage, 'success'); + } + } + } catch (error) { + console.error(messages?.log || 'Ошибка выполнения действия TDNS:', error); + if (messages?.error) { + updateStatus(messages.error, 'error'); + } + } finally { + $button.prop('disabled', false).text(originalText); + } +} + +function resetInstanceCounter() { + instanceCounter = 0; +} + +function getNextInstanceId() { + instanceCounter += 1; + return instanceCounter; +} + +function createInstanceRow(instance = {}) { + const uid = getNextInstanceId(); + const serverId = `tdns-server-${uid}`; + const tokenId = `tdns-token-${uid}`; + const forwarderId = `tdns-forwarder-${uid}`; + + return ` +
+
+

Инстанс

+ +
+
+ + +
+
+ + +
+
+ + + Адрес DNS сервера, на который будут перенаправляться запросы. +
+
+ `; +} + +function populateInstances() { + const instances = currentConfig.instances.length ? currentConfig.instances : []; + const $list = $(SELECTORS.instancesList); + resetInstanceCounter(); + $list.empty(); + instances.forEach(instance => { + $list.append(createInstanceRow(instance)); + }); +} + +function renderTDNSForm() { + const $container = $(SELECTORS.container); + $container.html(` +
+

Инстансы TDNS

+

Настройте подключения TDNS. Можно указать несколько серверов с собственными токенами.

+
+
+ +
+
+ +
+ +
+ `); + + populateInstances(); + attachEventHandlers(); +} + +function collectConfigFromForm() { + const instances = []; + $(SELECTORS.instancesList).find(`.${CLASS_NAMES.instance}`).each((_, element) => { + const $row = $(element); + const server = $row.find(`.${CLASS_NAMES.serverInput}`).val().trim(); + const token = $row.find(`.${CLASS_NAMES.tokenInput}`).val().trim(); + const forwarder = $row.find(`.${CLASS_NAMES.forwarderInput}`).val().trim(); + + if (server || token || forwarder) { + instances.push({ server, token, forwarder }); + } + }); + + return { instances }; +} + +async function loadConfig() { + try { + const fullConfig = await JSONRPC.System.getComponentConfig(TDNS_COMPONENT_NAME); + currentConfig = normalizeConfig(fullConfig); + return true; + } catch (error) { + console.error('Ошибка при загрузке конфига TDNS:', error); + currentConfig = { instances: [] }; + return false; + } +} + +function handleAddInstance() { + const $list = $(SELECTORS.instancesList); + $list.append(createInstanceRow({})); +} + +function handleRemoveInstance(event) { + event.preventDefault(); + $(event.currentTarget).closest(`.${CLASS_NAMES.instance}`).remove(); +} + +async function handleSave() { + const $button = $(SELECTORS.saveButton); + await runAction($button, 'Применение...', async () => { + const newConfig = collectConfigFromForm(); + await JSONRPC.System.setComponentConfig(TDNS_COMPONENT_NAME, newConfig); + currentConfig = normalizeConfig(newConfig); + populateInstances(); + }, { + success: 'Конфигурация TDNS успешно сохранена.', + error: 'Ошибка при сохранении конфигурации TDNS.', + log: 'Ошибка сохранения конфига TDNS' + }); +} + +function attachEventHandlers() { + $(SELECTORS.saveButton).off('click').on('click', handleSave); + $(SELECTORS.addInstanceButton).off('click').on('click', handleAddInstance); + $(SELECTORS.instancesList).off('click', `.${CLASS_NAMES.removeButton}`).on('click', `.${CLASS_NAMES.removeButton}`, handleRemoveInstance); +} + +function detachEventHandlers() { + $(SELECTORS.saveButton).off('click'); + $(SELECTORS.addInstanceButton).off('click'); + $(SELECTORS.instancesList).off('click', `.${CLASS_NAMES.removeButton}`); +} + +export const TDNSConfig = { + render: () => ` +

Настройка TDNS

+
+

Загрузка конфигурации...

+
+ `, + mount: async () => { + const success = await loadConfig(); + if (success) { + renderTDNSForm(); + } else { + $(SELECTORS.container).html('

Не удалось загрузить конфигурацию TDNS.

'); + } + }, + unmount: () => { + detachEventHandlers(); + clearStatus(); + currentConfig = { instances: [] }; + } +}; diff --git a/webui/src/styles/app.css b/webui/src/styles/app.css index 14dc3c9..d0719ef 100644 --- a/webui/src/styles/app.css +++ b/webui/src/styles/app.css @@ -128,6 +128,7 @@ html.dark-theme, body { text-decoration: none; transition: background-color 0.2s, color 0.2s; font-size: 15px; + position: relative; } .menu-item:hover { background-color: #2e3a4e; /* Чуть светлее, чем сайдбар */ @@ -137,6 +138,16 @@ html.dark-theme, body { background-color: var(--color-primary); color: white; } + +.menu-indicator { + display: inline-block; + width: 8px; + height: 8px; + background-color: #ef4444; + border-radius: 50%; + margin-left: 8px; + vertical-align: middle; +} .logout-btn { margin-top: 15px; border-top: 1px solid var(--color-border); @@ -178,6 +189,11 @@ html.dark-theme, body { transition: box-shadow 0.3s; } +.stat-card-highlight { + border-color: #ef4444; + box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.3); +} + .stat-card:hover { box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); } @@ -228,6 +244,57 @@ html.dark-theme, body { border-color: var(--color-border); } +.btn-link { + background: none; + border: none; + color: var(--color-error); + font-size: 15px; + font-weight: 600; + cursor: pointer; + padding: 4px; + border-radius: var(--border-radius); + transition: color 0.2s, background-color 0.2s; +} + +.btn-link:hover:not(:disabled) { + color: #f87171; + background-color: rgba(239, 68, 68, 0.12); +} + +.btn-link:disabled { + opacity: 0.6; + cursor: not-allowed; +} + +.log-entry { + background-color: transparent; + color: var(--color-text); +} + +.log-entry .log-entry-level { + font-size: 12px; + font-weight: 600; +} + +.log-entry .log-entry-message { + white-space: pre-wrap; + word-break: break-word; +} + +.log-level-info { + background-color: rgba(59, 130, 246, 0.08); +} + +.log-level-warning { + background-color: rgba(245, 158, 11, 0.12); + font-weight: 600; +} + +.log-level-severe { + background-color: rgba(239, 68, 68, 0.16); + font-weight: 600; +} + /* --- Стили для страницы Статистики (Дополнение: Ресурсы) --- */ .resource-group { diff --git a/webui/vite.config.js b/webui/vite.config.js index 3f435f5..b69d3f4 100644 --- a/webui/vite.config.js +++ b/webui/vite.config.js @@ -24,6 +24,10 @@ export default defineConfig({ path.resolve(__dirname, 'node_modules') ] } + }, + + build: { + outDir: path.resolve(__dirname, '../app/src/main/resources/htdocs') } // ----------------------------------------------------------------- }) \ No newline at end of file