diff --git a/.commitlintrc.json b/.commitlintrc.json new file mode 100644 index 00000000..cba65ea5 --- /dev/null +++ b/.commitlintrc.json @@ -0,0 +1,21 @@ +{ + "extends": ["@commitlint/config-conventional"], + "rules": { + "type-enum": [ + 2, + "always", + [ + "feat", + "fix", + "docs", + "style", + "refactor", + "perf", + "test", + "chore", + "revert" + ] + ], + "subject-case": [0] + } +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..3a6a1797 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +# Matches multiple files with brace expansion notation +[*.{js,jsx,ts,tsx,json,css,scss,md,yml,yaml}] +indent_style = space +indent_size = 2 + +# Markdown files +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..0716d3da --- /dev/null +++ b/.gitattributes @@ -0,0 +1,36 @@ +# Auto detect text files and perform LF normalization +* text=auto eol=lf + +# Source code +*.js text eol=lf +*.jsx text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.json text eol=lf +*.css text eol=lf +*.scss text eol=lf +*.html text eol=lf +*.md text eol=lf +*.yaml text eol=lf +*.yml text eol=lf + +# Scripts +*.sh text eol=lf +*.bash text eol=lf + +# Windows scripts should use CRLF +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +# Binary files +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.svg binary +*.woff binary +*.woff2 binary +*.ttf binary +*.eot binary diff --git a/.github/workflows/electron-build.yml b/.github/workflows/electron-build.yml index 63de08f7..670901d8 100644 --- a/.github/workflows/electron-build.yml +++ b/.github/workflows/electron-build.yml @@ -12,6 +12,7 @@ on: - all - windows - linux + - macos jobs: build-windows: @@ -91,3 +92,167 @@ jobs: name: Termix-Linux-Portable path: Termix-Linux-Portable.zip retention-days: 30 + + build-macos: + runs-on: macos-latest + if: github.event.inputs.build_type == 'macos' || github.event.inputs.build_type == 'all' + needs: [] + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 1 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: | + rm -f package-lock.json + npm install + npm install --force @rollup/rollup-darwin-arm64 + + - name: Check for Code Signing Certificates + id: check_certs + run: | + if [ -n "${{ secrets.MAC_BUILD_CERTIFICATE_BASE64 }}" ] && [ -n "${{ secrets.MAC_P12_PASSWORD }}" ]; then + echo "has_certs=true" >> $GITHUB_OUTPUT + else + echo "has_certs=false" >> $GITHUB_OUTPUT + echo "⚠️ Code signing certificates not configured. MAS build will be unsigned." + fi + + - name: Import Code Signing Certificates + if: steps.check_certs.outputs.has_certs == 'true' + env: + MAC_BUILD_CERTIFICATE_BASE64: ${{ secrets.MAC_BUILD_CERTIFICATE_BASE64 }} + MAC_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.MAC_INSTALLER_CERTIFICATE_BASE64 }} + MAC_P12_PASSWORD: ${{ secrets.MAC_P12_PASSWORD }} + MAC_KEYCHAIN_PASSWORD: ${{ secrets.MAC_KEYCHAIN_PASSWORD }} + run: | + APP_CERT_PATH=$RUNNER_TEMP/app_certificate.p12 + INSTALLER_CERT_PATH=$RUNNER_TEMP/installer_certificate.p12 + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + # Decode certificates + echo -n "$MAC_BUILD_CERTIFICATE_BASE64" | base64 --decode -o $APP_CERT_PATH + + if [ -n "$MAC_INSTALLER_CERTIFICATE_BASE64" ]; then + echo "Decoding installer certificate..." + echo -n "$MAC_INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $INSTALLER_CERT_PATH + else + echo "⚠️ MAC_INSTALLER_CERTIFICATE_BASE64 is empty" + fi + + # Create and configure keychain + security create-keychain -p "$MAC_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$MAC_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # Import application certificate + echo "Importing application certificate..." + security import $APP_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + + # Import installer certificate if it exists + if [ -f "$INSTALLER_CERT_PATH" ]; then + echo "Importing installer certificate..." + security import $INSTALLER_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + else + echo "⚠️ Installer certificate file not found, skipping import" + fi + + security list-keychain -d user -s $KEYCHAIN_PATH + + echo "Imported certificates:" + security find-identity -v -p codesigning $KEYCHAIN_PATH + + - name: Set version for build + if: steps.check_certs.outputs.has_certs == 'true' + run: | + # Get current version and extract major.minor + CURRENT_VERSION=$(node -p "require('./package.json').version") + MAJOR_MINOR=$(echo $CURRENT_VERSION | cut -d. -f1-2) + NEW_VERSION="${MAJOR_MINOR}.${{ github.run_number }}" + + npm version $NEW_VERSION --no-git-tag-version + echo "✅ Version set to: $NEW_VERSION" + + - name: Build macOS App Store Package + if: steps.check_certs.outputs.has_certs == 'true' + env: + ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES: true + run: npm run build:mac + + - name: List release directory + if: steps.check_certs.outputs.has_certs == 'true' + run: | + echo "Contents of release directory:" + ls -R release/ || echo "Release directory not found" + + - name: Upload macOS MAS Artifact + if: steps.check_certs.outputs.has_certs == 'true' + uses: actions/upload-artifact@v4 + with: + name: Termix-macOS-MAS + path: | + release/*.pkg + release/mas/*.pkg + retention-days: 30 + if-no-files-found: warn + + - name: Check for App Store Connect API credentials + if: steps.check_certs.outputs.has_certs == 'true' + id: check_asc_creds + run: | + if [ -n "${{ secrets.APPLE_KEY_ID }}" ] && [ -n "${{ secrets.APPLE_ISSUER_ID }}" ] && [ -n "${{ secrets.APPLE_KEY_CONTENT }}" ]; then + echo "has_credentials=true" >> $GITHUB_OUTPUT + echo "✅ App Store Connect API credentials found. Will deploy to App Store Connect." + else + echo "has_credentials=false" >> $GITHUB_OUTPUT + echo "⚠️ App Store Connect API credentials not configured. Skipping deployment." + echo "Add APPLE_KEY_ID, APPLE_ISSUER_ID, and APPLE_KEY_CONTENT secrets to enable automatic deployment." + fi + + - name: Setup Ruby for Fastlane + if: steps.check_asc_creds.outputs.has_credentials == 'true' + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2' + bundler-cache: false + + - name: Install Fastlane + if: steps.check_asc_creds.outputs.has_credentials == 'true' + run: | + gem install fastlane -N + fastlane --version + + - name: Deploy to App Store Connect (TestFlight) + if: steps.check_asc_creds.outputs.has_credentials == 'true' + run: | + PKG_FILE=$(find release -name "*.pkg" -type f | head -n 1) + if [ -z "$PKG_FILE" ]; then + echo "Error: No .pkg file found in release directory" + exit 1 + fi + echo "Found package: $PKG_FILE" + + # Create API key file + mkdir -p ~/private_keys + echo "${{ secrets.APPLE_KEY_CONTENT }}" | base64 --decode > ~/private_keys/AuthKey_${{ secrets.APPLE_KEY_ID }}.p8 + + # Upload to App Store Connect using xcrun altool + xcrun altool --upload-app -f "$PKG_FILE" \ + --type macos \ + --apiKey "${{ secrets.APPLE_KEY_ID }}" \ + --apiIssuer "${{ secrets.APPLE_ISSUER_ID }}" + + echo "✅ Upload complete! Build will appear in App Store Connect after processing (10-30 minutes)" + continue-on-error: true + + - name: Clean up keychain + if: always() && steps.check_certs.outputs.has_certs == 'true' + run: | + security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 00000000..5d0df61f --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,35 @@ +name: PR Check + +on: + pull_request: + branches: [main, dev-*] + +jobs: + lint-and-build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: | + rm -rf node_modules package-lock.json + npm install + + - name: Run ESLint + run: npx eslint . + + - name: Run Prettier check + run: npx prettier --check . + + - name: Type check + run: npx tsc --noEmit + + - name: Build + run: npm run build diff --git a/.gitignore b/.gitignore index a3188d42..67859b45 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ dist-ssr /.claude/ /ssl/ .env +/.mcp.json diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 00000000..0a4b97de --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1 @@ +npx --no -- commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..2312dc58 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged diff --git a/.nvmrc b/.nvmrc index 2bd5a0a9..209e3ef4 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22 +20 diff --git a/.prettierignore b/.prettierignore index 1b8ac889..5f52bf45 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,23 @@ # Ignore artifacts: build coverage +dist +dist-ssr +release + +# Dependencies +node_modules +package-lock.json +pnpm-lock.yaml +yarn.lock + +# Database +db + +# Environment +.env + +# Misc +*.min.js +*.min.css +openapi.json diff --git a/.prettierrc b/.prettierrc index 0967ef42..fd873cbb 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1 +1,9 @@ -{} +{ + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "all", + "printWidth": 80, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..034db5d6 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "editorconfig.editorconfig" + ] +} diff --git a/README.md b/README.md index 071af00d..704f4c17 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ access, SSH tunneling capabilities, and remote file management, with many more t - **SSH Terminal Access** - Full-featured terminal with split-screen support (up to 4 panels) and tab system - **SSH Tunnel Management** - Create and manage SSH tunnels with automatic reconnection and health monitoring - **Remote File Manager** - Manage files directly on remote servers with support for viewing and editing code, images, audio, and video. Upload, download, rename, delete, and move files seamlessly. -- **SSH Host Manager** - Save, organize, and manage your SSH connections with tags and folders and easily save reusable login info while being able to automate the deploying of SSH keys +- **SSH Host Manager** - Save, organize, and manage your SSH connections with tags and folders, and easily save reusable login info while being able to automate the deployment of SSH keys - **Server Stats** - View CPU, memory, and HDD usage on any SSH server - **User Authentication** - Secure user management with admin controls and OIDC and 2FA (TOTP) support - **Database Encryption** - SQLite database files encrypted at rest with automatic encryption/decryption diff --git a/build/Termix_Mac_App_Store.provisionprofile b/build/Termix_Mac_App_Store.provisionprofile new file mode 100644 index 00000000..8e87f405 Binary files /dev/null and b/build/Termix_Mac_App_Store.provisionprofile differ diff --git a/build/entitlements.mas.inherit.plist b/build/entitlements.mas.inherit.plist new file mode 100644 index 00000000..eb23e9ac --- /dev/null +++ b/build/entitlements.mas.inherit.plist @@ -0,0 +1,16 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.inherit + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/build/entitlements.mas.plist b/build/entitlements.mas.plist new file mode 100644 index 00000000..c9ac7c4a --- /dev/null +++ b/build/entitlements.mas.plist @@ -0,0 +1,20 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.network.server + + com.apple.security.files.user-selected.read-write + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/docker/Dockerfile b/docker/Dockerfile index 8bf66283..555114e6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,7 @@ FROM node:22-slim AS deps WORKDIR /app -RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* +RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* COPY package*.json ./ @@ -82,8 +82,8 @@ COPY --chown=node:node package.json ./ VOLUME ["/app/data"] -EXPOSE ${PORT} 30001 30002 30003 30004 30005 +EXPOSE ${PORT} 30001 30002 30003 30004 30005 30006 COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh -CMD ["/entrypoint.sh"] \ No newline at end of file +CMD ["/entrypoint.sh"] diff --git a/docker/nginx-https.conf b/docker/nginx-https.conf index f64e8e4e..53caa38b 100644 --- a/docker/nginx-https.conf +++ b/docker/nginx-https.conf @@ -92,7 +92,7 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; @@ -101,18 +101,18 @@ http { location ~ ^/database(/.*)?$ { client_max_body_size 5G; client_body_timeout 300s; - + proxy_pass http://127.0.0.1:30001; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; - + proxy_request_buffering off; proxy_buffering off; } @@ -120,18 +120,18 @@ http { location ~ ^/db(/.*)?$ { client_max_body_size 5G; client_body_timeout 300s; - + proxy_pass http://127.0.0.1:30001; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; - + proxy_request_buffering off; proxy_buffering off; } @@ -216,18 +216,18 @@ http { location /ssh/file_manager/ssh/ { client_max_body_size 5G; client_body_timeout 300s; - + proxy_pass http://127.0.0.1:30004; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - + proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; - + proxy_request_buffering off; proxy_buffering off; } @@ -259,9 +259,27 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } + location ~ ^/uptime(/.*)?$ { + proxy_pass http://127.0.0.1:30006; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~ ^/activity(/.*)?$ { + proxy_pass http://127.0.0.1:30006; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } -} \ No newline at end of file +} diff --git a/docker/nginx.conf b/docker/nginx.conf index c180c180..5dde75d3 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -248,6 +248,24 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } + location ~ ^/uptime(/.*)?$ { + proxy_pass http://127.0.0.1:30006; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~ ^/activity(/.*)?$ { + proxy_pass http://127.0.0.1:30006; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; diff --git a/electron-builder.json b/electron-builder.json index 9fb6d36b..816c1351 100644 --- a/electron-builder.json +++ b/electron-builder.json @@ -1,6 +1,7 @@ { - "appId": "com.termix.app", + "appId": "com.karmaa.termix", "productName": "Termix", + "publish": null, "directories": { "output": "release" }, @@ -21,7 +22,7 @@ }, "buildDependenciesFromSource": false, "nodeGypRebuild": false, - "npmRebuild": false, + "npmRebuild": true, "win": { "target": "nsis", "icon": "public/icon.ico", @@ -58,5 +59,35 @@ "StartupWMClass": "termix" } } + }, + "mac": { + "target": [ + { + "target": "mas", + "arch": "universal" + } + ], + "icon": "public/icon.icns", + "category": "public.app-category.developer-tools", + "hardenedRuntime": true, + "gatekeeperAssess": false, + "entitlements": "build/entitlements.mas.plist", + "entitlementsInherit": "build/entitlements.mas.inherit.plist", + "type": "distribution", + "minimumSystemVersion": "10.15" + }, + "mas": { + "provisioningProfile": "build/Termix_Mac_App_Store.provisionprofile", + "entitlements": "build/entitlements.mas.plist", + "entitlementsInherit": "build/entitlements.mas.inherit.plist", + "hardenedRuntime": false, + "gatekeeperAssess": false, + "asarUnpack": ["**/*.node"], + "type": "distribution", + "category": "public.app-category.developer-tools", + "extendInfo": { + "ITSAppUsesNonExemptEncryption": false, + "NSAppleEventsUsageDescription": "Termix needs access to control other applications for terminal operations." + } } } diff --git a/package-lock.json b/package-lock.json index bd087a93..4ac96ca2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "termix", - "version": "1.7.2", + "version": "1.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "termix", - "version": "1.7.2", + "version": "1.8.0", "dependencies": { "@codemirror/autocomplete": "^6.18.7", "@codemirror/commands": "^6.3.3", @@ -29,7 +29,7 @@ "@radix-ui/react-switch": "^1.2.5", "@radix-ui/react-tabs": "^1.1.12", "@radix-ui/react-tooltip": "^1.2.8", - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/vite": "^4.1.14", "@types/bcryptjs": "^2.4.6", "@types/cookie-parser": "^1.4.9", "@types/jszip": "^3.4.0", @@ -80,16 +80,21 @@ "react-simple-keyboard": "^3.8.120", "react-syntax-highlighter": "^15.6.6", "react-xtermjs": "^1.0.10", + "recharts": "^3.2.1", "remark-gfm": "^4.0.1", "sonner": "^2.0.7", "speakeasy": "^2.0.0", "ssh2": "^1.16.0", "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.14", "wait-on": "^9.0.1", "ws": "^8.18.3", "zod": "^4.0.5" }, "devDependencies": { + "@commitlint/cli": "^20.1.0", + "@commitlint/config-conventional": "^20.0.0", + "@electron/notarize": "^2.5.0", "@eslint/js": "^9.34.0", "@types/better-sqlite3": "^7.6.13", "@types/cors": "^2.8.19", @@ -108,16 +113,37 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.3.0", + "husky": "^9.1.7", + "lint-staged": "^16.2.3", "prettier": "3.6.2", "typescript": "~5.9.2", "typescript-eslint": "^8.40.0", "vite": "^7.1.5" } }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "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/helper-validator-identifier": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/runtime": { "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -125,9 +151,8 @@ }, "node_modules/@codemirror/autocomplete": { "version": "6.19.0", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.19.0.tgz", - "integrity": "sha512-61Hfv3cF07XvUxNeC3E7jhG8XNi1Yom1G0lRC936oLnlF+jrbrv8rc/J98XlYzcsAoTVupfsf5fLej1aI8kyIg==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", @@ -137,8 +162,6 @@ }, "node_modules/@codemirror/commands": { "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.8.1.tgz", - "integrity": "sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -149,8 +172,6 @@ }, "node_modules/@codemirror/lang-angular": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-angular/-/lang-angular-0.1.4.tgz", - "integrity": "sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==", "license": "MIT", "dependencies": { "@codemirror/lang-html": "^6.0.0", @@ -163,8 +184,6 @@ }, "node_modules/@codemirror/lang-cpp": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", - "integrity": "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -173,9 +192,8 @@ }, "node_modules/@codemirror/lang-css": { "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", - "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", @@ -186,8 +204,6 @@ }, "node_modules/@codemirror/lang-go": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz", - "integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -199,9 +215,8 @@ }, "node_modules/@codemirror/lang-html": { "version": "6.4.10", - "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.10.tgz", - "integrity": "sha512-h/SceTVsN5r+WE+TVP2g3KDvNoSzbSrtZXCKo4vkKdbfT5t4otuVgngGdFukOO/rwRD2++pCxoh6xD4TEVMkQA==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", @@ -216,8 +231,6 @@ }, "node_modules/@codemirror/lang-java": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.2.tgz", - "integrity": "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -226,9 +239,8 @@ }, "node_modules/@codemirror/lang-javascript": { "version": "6.2.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz", - "integrity": "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", @@ -241,8 +253,6 @@ }, "node_modules/@codemirror/lang-json": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", - "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -251,8 +261,6 @@ }, "node_modules/@codemirror/lang-less": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-less/-/lang-less-6.0.2.tgz", - "integrity": "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==", "license": "MIT", "dependencies": { "@codemirror/lang-css": "^6.2.0", @@ -264,8 +272,6 @@ }, "node_modules/@codemirror/lang-liquid": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.3.0.tgz", - "integrity": "sha512-fY1YsUExcieXRTsCiwX/bQ9+PbCTA/Fumv7C7mTUZHoFkibfESnaXwpr2aKH6zZVwysEunsHHkaIpM/pl3xETQ==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -280,8 +286,6 @@ }, "node_modules/@codemirror/lang-markdown": { "version": "6.3.4", - "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.3.4.tgz", - "integrity": "sha512-fBm0BO03azXnTAsxhONDYHi/qWSI+uSEIpzKM7h/bkIc9fHnFp9y7KTMXKON0teNT97pFhc1a9DQTtWBYEZ7ug==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.7.1", @@ -295,8 +299,6 @@ }, "node_modules/@codemirror/lang-php": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.2.tgz", - "integrity": "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==", "license": "MIT", "dependencies": { "@codemirror/lang-html": "^6.0.0", @@ -308,8 +310,6 @@ }, "node_modules/@codemirror/lang-python": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz", - "integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.3.2", @@ -321,8 +321,6 @@ }, "node_modules/@codemirror/lang-rust": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz", - "integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -331,8 +329,6 @@ }, "node_modules/@codemirror/lang-sass": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", - "integrity": "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==", "license": "MIT", "dependencies": { "@codemirror/lang-css": "^6.2.0", @@ -344,8 +340,6 @@ }, "node_modules/@codemirror/lang-sql": { "version": "6.10.0", - "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", - "integrity": "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -358,8 +352,6 @@ }, "node_modules/@codemirror/lang-vue": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", - "integrity": "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==", "license": "MIT", "dependencies": { "@codemirror/lang-html": "^6.0.0", @@ -372,8 +364,6 @@ }, "node_modules/@codemirror/lang-wast": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", - "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -384,8 +374,6 @@ }, "node_modules/@codemirror/lang-xml": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", - "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -398,8 +386,6 @@ }, "node_modules/@codemirror/lang-yaml": { "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz", - "integrity": "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -413,9 +399,8 @@ }, "node_modules/@codemirror/language": { "version": "6.11.3", - "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.3.tgz", - "integrity": "sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", @@ -427,8 +412,6 @@ }, "node_modules/@codemirror/language-data": { "version": "6.5.1", - "resolved": "https://registry.npmjs.org/@codemirror/language-data/-/language-data-6.5.1.tgz", - "integrity": "sha512-0sWxeUSNlBr6OmkqybUTImADFUP0M3P0IiSde4nc24bz/6jIYzqYSgkOSLS+CBIoW1vU8Q9KUWXscBXeoMVC9w==", "license": "MIT", "dependencies": { "@codemirror/lang-angular": "^0.1.0", @@ -457,8 +440,6 @@ }, "node_modules/@codemirror/legacy-modes": { "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.2.tgz", - "integrity": "sha512-/jJbwSTazlQEDOQw2FJ8LEEKVS72pU0lx6oM54kGpL8t/NJ2Jda3CZ4pcltiKTdqYSRk3ug1B3pil1gsjA6+8Q==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0" @@ -466,8 +447,6 @@ }, "node_modules/@codemirror/lint": { "version": "6.8.5", - "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.5.tgz", - "integrity": "sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", @@ -477,8 +456,6 @@ }, "node_modules/@codemirror/search": { "version": "6.5.11", - "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz", - "integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.0.0", @@ -488,17 +465,14 @@ }, "node_modules/@codemirror/state": { "version": "6.5.2", - "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", - "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", "license": "MIT", + "peer": true, "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "node_modules/@codemirror/theme-one-dark": { "version": "6.1.3", - "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", - "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -509,9 +483,8 @@ }, "node_modules/@codemirror/view": { "version": "6.38.4", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.4.tgz", - "integrity": "sha512-hduz0suCcUSC/kM8Fq3A9iLwInJDl8fD1xLpTIk+5xkNm8z/FT7UsIa9sOXrkpChh+XXc18RzswE8QqELsVl+g==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", @@ -519,10 +492,380 @@ "w3c-keyname": "^2.2.4" } }, + "node_modules/@commitlint/cli": { + "version": "20.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^20.0.0", + "@commitlint/lint": "^20.0.0", + "@commitlint/load": "^20.1.0", + "@commitlint/read": "^20.0.0", + "@commitlint/types": "^20.0.0", + "tinyexec": "^1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.0.0", + "conventional-changelog-conventionalcommits": "^7.0.2" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.0.0", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/config-validator/node_modules/ajv": { + "version": "8.17.1", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@commitlint/ensure": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.0.0", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format/node_modules/chalk": { + "version": "5.6.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.0.0", + "semver": "^7.6.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.7.2", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^20.0.0", + "@commitlint/parse": "^20.0.0", + "@commitlint/rules": "^20.0.0", + "@commitlint/types": "^20.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load": { + "version": "20.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.0.0", + "@commitlint/execute-rule": "^20.0.0", + "@commitlint/resolve-extends": "^20.1.0", + "@commitlint/types": "^20.0.0", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^6.1.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/load/node_modules/chalk": { + "version": "5.6.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@commitlint/message": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^20.0.0", + "conventional-changelog-angular": "^7.0.0", + "conventional-commits-parser": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/read": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^20.0.0", + "@commitlint/types": "^20.0.0", + "git-raw-commits": "^4.0.0", + "minimist": "^1.2.8", + "tinyexec": "^1.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "20.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^20.0.0", + "@commitlint/types": "^20.0.0", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/resolve-extends/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@commitlint/rules": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^20.0.0", + "@commitlint/message": "^20.0.0", + "@commitlint/to-lines": "^20.0.0", + "@commitlint/types": "^20.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^7.0.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level/node_modules/find-up": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^7.2.0", + "path-exists": "^5.0.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/locate-path": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-limit": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-locate": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/path-exists": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@commitlint/top-level/node_modules/yocto-queue": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/types": { + "version": "20.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" + }, + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/types/node_modules/chalk": { + "version": "5.6.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/@develar/schema-utils": { "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", - "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", "dev": true, "license": "MIT", "dependencies": { @@ -539,8 +882,6 @@ }, "node_modules/@electron/asar": { "version": "3.2.18", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz", - "integrity": "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==", "dev": true, "license": "MIT", "dependencies": { @@ -557,8 +898,6 @@ }, "node_modules/@electron/asar/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -570,8 +909,6 @@ }, "node_modules/@electron/fuses": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@electron/fuses/-/fuses-1.8.0.tgz", - "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", "dev": true, "license": "MIT", "dependencies": { @@ -585,8 +922,6 @@ }, "node_modules/@electron/fuses/node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "license": "MIT", "dependencies": { @@ -601,8 +936,6 @@ }, "node_modules/@electron/fuses/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -614,8 +947,6 @@ }, "node_modules/@electron/fuses/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -624,8 +955,6 @@ }, "node_modules/@electron/get": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", "dev": true, "license": "MIT", "dependencies": { @@ -646,8 +975,6 @@ }, "node_modules/@electron/get/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": { @@ -664,8 +991,6 @@ }, "node_modules/@electron/get/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" }, @@ -696,8 +1021,6 @@ }, "node_modules/@electron/node-gyp/node_modules/brace-expansion": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -706,9 +1029,6 @@ }, "node_modules/@electron/node-gyp/node_modules/glob": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -727,8 +1047,6 @@ }, "node_modules/@electron/node-gyp/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", "dependencies": { @@ -740,8 +1058,6 @@ }, "node_modules/@electron/node-gyp/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "license": "ISC", "engines": { @@ -750,8 +1066,6 @@ }, "node_modules/@electron/node-gyp/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -763,8 +1077,6 @@ }, "node_modules/@electron/node-gyp/node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "license": "ISC", "dependencies": { @@ -781,8 +1093,6 @@ }, "node_modules/@electron/notarize": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", - "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", "dev": true, "license": "MIT", "dependencies": { @@ -796,8 +1106,6 @@ }, "node_modules/@electron/notarize/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": { @@ -814,8 +1122,6 @@ }, "node_modules/@electron/notarize/node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "license": "MIT", "dependencies": { @@ -830,8 +1136,6 @@ }, "node_modules/@electron/notarize/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -843,15 +1147,11 @@ }, "node_modules/@electron/notarize/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/@electron/notarize/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -860,8 +1160,6 @@ }, "node_modules/@electron/osx-sign": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -882,8 +1180,6 @@ }, "node_modules/@electron/osx-sign/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": { @@ -900,8 +1196,6 @@ }, "node_modules/@electron/osx-sign/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -915,8 +1209,6 @@ }, "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, "license": "MIT", "engines": { @@ -928,8 +1220,6 @@ }, "node_modules/@electron/osx-sign/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -941,15 +1231,11 @@ }, "node_modules/@electron/osx-sign/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/@electron/osx-sign/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -958,12 +1244,10 @@ }, "node_modules/@electron/rebuild": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.0.tgz", - "integrity": "sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==", "dev": true, "license": "MIT", "dependencies": { - "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", + "@electron/node-gyp": "https://github.com/electron/node-gyp#06b29aafb7708acef8b3669835c8a7857ebc92d2", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.1.1", @@ -987,8 +1271,6 @@ }, "node_modules/@electron/rebuild/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": { @@ -1005,8 +1287,6 @@ }, "node_modules/@electron/rebuild/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1020,8 +1300,6 @@ }, "node_modules/@electron/rebuild/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -1033,8 +1311,6 @@ }, "node_modules/@electron/rebuild/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "license": "ISC", "engines": { @@ -1043,15 +1319,11 @@ }, "node_modules/@electron/rebuild/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/@electron/rebuild/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -1063,8 +1335,6 @@ }, "node_modules/@electron/rebuild/node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "license": "ISC", "dependencies": { @@ -1081,8 +1351,6 @@ }, "node_modules/@electron/rebuild/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -1091,8 +1359,6 @@ }, "node_modules/@electron/universal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", "dev": true, "license": "MIT", "dependencies": { @@ -1110,8 +1376,6 @@ }, "node_modules/@electron/universal/node_modules/brace-expansion": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1120,8 +1384,6 @@ }, "node_modules/@electron/universal/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": { @@ -1138,8 +1400,6 @@ }, "node_modules/@electron/universal/node_modules/fs-extra": { "version": "11.3.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", - "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, "license": "MIT", "dependencies": { @@ -1153,8 +1413,6 @@ }, "node_modules/@electron/universal/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -1166,8 +1424,6 @@ }, "node_modules/@electron/universal/node_modules/minimatch": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { @@ -1182,15 +1438,11 @@ }, "node_modules/@electron/universal/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/@electron/universal/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -1199,12 +1451,9 @@ }, "node_modules/@electron/windows-sign": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", - "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", "dev": true, "license": "BSD-2-Clause", "optional": true, - "peer": true, "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", @@ -1221,12 +1470,9 @@ }, "node_modules/@electron/windows-sign/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", "optional": true, - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -1241,12 +1487,9 @@ }, "node_modules/@electron/windows-sign/node_modules/fs-extra": { "version": "11.3.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", - "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1258,12 +1501,9 @@ }, "node_modules/@electron/windows-sign/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -1273,429 +1513,21 @@ }, "node_modules/@electron/windows-sign/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", - "optional": true, - "peer": true + "optional": true }, "node_modules/@electron/windows-sign/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": ">= 10.0.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", - "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", - "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", - "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", - "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", - "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", - "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", - "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", - "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", - "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", - "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", - "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", - "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", - "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", - "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", - "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", - "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", - "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", - "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", - "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", - "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", - "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", - "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", - "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", - "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", - "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, "node_modules/@esbuild/win32-x64": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", - "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", "cpu": [ "x64" ], @@ -1710,8 +1542,6 @@ }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "license": "MIT", "dependencies": { @@ -1729,8 +1559,6 @@ }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1742,8 +1570,6 @@ }, "node_modules/@eslint-community/regexpp": { "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -1752,8 +1578,6 @@ }, "node_modules/@eslint/config-array": { "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1767,8 +1591,6 @@ }, "node_modules/@eslint/config-array/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": { @@ -1785,8 +1607,6 @@ }, "node_modules/@eslint/config-array/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -1798,15 +1618,11 @@ }, "node_modules/@eslint/config-array/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/@eslint/config-helpers": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1815,8 +1631,6 @@ }, "node_modules/@eslint/core": { "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1828,8 +1642,6 @@ }, "node_modules/@eslint/eslintrc": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1852,8 +1664,6 @@ }, "node_modules/@eslint/eslintrc/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": { @@ -1870,8 +1680,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", "engines": { @@ -1883,8 +1691,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -1896,15 +1702,11 @@ }, "node_modules/@eslint/eslintrc/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/@eslint/js": { "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", "dev": true, "license": "MIT", "engines": { @@ -1916,8 +1718,6 @@ }, "node_modules/@eslint/object-schema": { "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1926,8 +1726,6 @@ }, "node_modules/@eslint/plugin-kit": { "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1940,8 +1738,6 @@ }, "node_modules/@floating-ui/core": { "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", - "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", "license": "MIT", "dependencies": { "@floating-ui/utils": "^0.2.10" @@ -1949,8 +1745,6 @@ }, "node_modules/@floating-ui/dom": { "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", - "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", "license": "MIT", "dependencies": { "@floating-ui/core": "^1.7.3", @@ -1959,8 +1753,6 @@ }, "node_modules/@floating-ui/react-dom": { "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", - "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.7.4" @@ -1972,21 +1764,15 @@ }, "node_modules/@floating-ui/utils": { "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, "node_modules/@gar/promisify": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true, "license": "MIT" }, "node_modules/@hapi/address": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", - "integrity": "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA==", "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^11.0.2" @@ -1997,26 +1783,18 @@ }, "node_modules/@hapi/formula": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hapi/formula/-/formula-3.0.2.tgz", - "integrity": "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw==", "license": "BSD-3-Clause" }, "node_modules/@hapi/hoek": { "version": "11.0.7", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-11.0.7.tgz", - "integrity": "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==", "license": "BSD-3-Clause" }, "node_modules/@hapi/pinpoint": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@hapi/pinpoint/-/pinpoint-2.0.1.tgz", - "integrity": "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q==", "license": "BSD-3-Clause" }, "node_modules/@hapi/tlds": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@hapi/tlds/-/tlds-1.1.3.tgz", - "integrity": "sha512-QIvUMB5VZ8HMLZF9A2oWr3AFM430QC8oGd0L35y2jHpuW6bIIca6x/xL7zUf4J7L9WJ3qjz+iJII8ncaeMbpSg==", "license": "BSD-3-Clause", "engines": { "node": ">=14.0.0" @@ -2024,8 +1802,6 @@ }, "node_modules/@hapi/topo": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-6.0.2.tgz", - "integrity": "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==", "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^11.0.2" @@ -2033,8 +1809,6 @@ }, "node_modules/@hookform/resolvers": { "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.2.2.tgz", - "integrity": "sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==", "license": "MIT", "dependencies": { "@standard-schema/utils": "^0.3.0" @@ -2045,8 +1819,6 @@ }, "node_modules/@humanfs/core": { "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2055,8 +1827,6 @@ }, "node_modules/@humanfs/node": { "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2069,8 +1839,6 @@ }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2083,8 +1851,6 @@ }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2097,8 +1863,6 @@ }, "node_modules/@iconify/react": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@iconify/react/-/react-5.2.1.tgz", - "integrity": "sha512-37GDR3fYDZmnmUn9RagyaX+zca24jfVOMY8E1IXTqJuE8pxNtN51KWPQe3VODOWvuUurq7q9uUu3CFrpqj5Iqg==", "license": "MIT", "dependencies": { "@iconify/types": "^2.0.0" @@ -2112,14 +1876,10 @@ }, "node_modules/@iconify/types": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", "license": "MIT" }, "node_modules/@isaacs/balanced-match": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", "dev": true, "license": "MIT", "engines": { @@ -2128,8 +1888,6 @@ }, "node_modules/@isaacs/brace-expansion": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", "dev": true, "license": "MIT", "dependencies": { @@ -2141,8 +1899,6 @@ }, "node_modules/@isaacs/cliui": { "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "license": "ISC", "dependencies": { @@ -2159,8 +1915,6 @@ }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -2172,8 +1926,6 @@ }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { @@ -2185,15 +1937,11 @@ }, "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, "license": "MIT" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { @@ -2210,8 +1958,6 @@ }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -2226,8 +1972,6 @@ }, "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2310,14 +2054,11 @@ }, "node_modules/@lezer/common": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", - "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@lezer/cpp": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.3.tgz", - "integrity": "sha512-ykYvuFQKGsRi6IcE+/hCSGUhb/I4WPjd3ELhEblm2wS2cOznDFzO+ubK2c+ioysOnlZ3EduV+MVQFCPzAIoY3w==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2327,8 +2068,6 @@ }, "node_modules/@lezer/css": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.0.tgz", - "integrity": "sha512-pBL7hup88KbI7hXnZV3PQsn43DHy6TWyzuyk2AO9UyoXcDltvIdqWKE1dLL/45JVZ+YZkHe1WVHqO6wugZZWcw==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2338,8 +2077,6 @@ }, "node_modules/@lezer/go": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.1.tgz", - "integrity": "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2349,17 +2086,14 @@ }, "node_modules/@lezer/highlight": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", - "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", "license": "MIT", + "peer": true, "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/html": { "version": "1.3.12", - "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.12.tgz", - "integrity": "sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2369,8 +2103,6 @@ }, "node_modules/@lezer/java": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", - "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2380,9 +2112,8 @@ }, "node_modules/@lezer/javascript": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", - "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", "license": "MIT", + "peer": true, "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", @@ -2391,8 +2122,6 @@ }, "node_modules/@lezer/json": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", - "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2402,17 +2131,14 @@ }, "node_modules/@lezer/lr": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", - "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", "license": "MIT", + "peer": true, "dependencies": { "@lezer/common": "^1.0.0" } }, "node_modules/@lezer/markdown": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.4.3.tgz", - "integrity": "sha512-kfw+2uMrQ/wy/+ONfrH83OkdFNM0ye5Xq96cLlaCy7h5UT9FO54DU4oRoIc0CSBh5NWmWuiIJA7NGLMJbQ+Oxg==", "license": "MIT", "dependencies": { "@lezer/common": "^1.0.0", @@ -2421,8 +2147,6 @@ }, "node_modules/@lezer/php": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.5.tgz", - "integrity": "sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2432,8 +2156,6 @@ }, "node_modules/@lezer/python": { "version": "1.1.18", - "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.18.tgz", - "integrity": "sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2443,8 +2165,6 @@ }, "node_modules/@lezer/rust": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", - "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2454,8 +2174,6 @@ }, "node_modules/@lezer/sass": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.1.0.tgz", - "integrity": "sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2465,8 +2183,6 @@ }, "node_modules/@lezer/xml": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", - "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2476,8 +2192,6 @@ }, "node_modules/@lezer/yaml": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.3.tgz", - "integrity": "sha512-GuBLekbw9jDBDhGur82nuwkxKQ+a3W5H0GfaAthDXcAu+XdpS43VlnxA9E9hllkpSP5ellRDKjLLj7Lu9Wr6xA==", "license": "MIT", "dependencies": { "@lezer/common": "^1.2.0", @@ -2487,8 +2201,6 @@ }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", "dev": true, "funding": [ { @@ -2510,8 +2222,6 @@ }, "node_modules/@malept/flatpak-bundler": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", - "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2526,8 +2236,6 @@ }, "node_modules/@malept/flatpak-bundler/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": { @@ -2544,8 +2252,6 @@ }, "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2560,8 +2266,6 @@ }, "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -2573,15 +2277,11 @@ }, "node_modules/@malept/flatpak-bundler/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/@malept/flatpak-bundler/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -2590,14 +2290,10 @@ }, "node_modules/@marijn/find-cluster-break": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", - "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "license": "MIT" }, "node_modules/@monaco-editor/loader": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz", - "integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==", "license": "MIT", "dependencies": { "state-local": "^1.0.6" @@ -2605,8 +2301,6 @@ }, "node_modules/@monaco-editor/react": { "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz", - "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==", "license": "MIT", "dependencies": { "@monaco-editor/loader": "^1.5.0" @@ -2619,8 +2313,6 @@ }, "node_modules/@mux/mux-data-google-ima": { "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@mux/mux-data-google-ima/-/mux-data-google-ima-0.2.8.tgz", - "integrity": "sha512-0ZEkHdcZ6bS8QtcjFcoJeZxJTpX7qRIledf4q1trMWPznugvtajCjCM2kieK/pzkZj1JM6liDRFs1PJSfVUs2A==", "license": "MIT", "dependencies": { "mux-embed": "5.9.0" @@ -2628,8 +2320,6 @@ }, "node_modules/@mux/mux-player": { "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@mux/mux-player/-/mux-player-3.6.1.tgz", - "integrity": "sha512-QidL9CSkRBwa49ItphuDXWtarAiskP8AG/+vj5u0LsCa+VqObQxPfxE9t5S9YO/SDYHXqDMviMpmSzotSROGUQ==", "license": "MIT", "dependencies": { "@mux/mux-video": "0.27.0", @@ -2640,8 +2330,6 @@ }, "node_modules/@mux/mux-player-react": { "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@mux/mux-player-react/-/mux-player-react-3.6.1.tgz", - "integrity": "sha512-YKIieu9GmFI73+1EcAvd63ftZ0Z9ilGbWo2dGXqQeyCEcagIN0oEcXWUPuIuxhvYB0XXsxB8RBAD8SigHkCYAQ==", "license": "MIT", "dependencies": { "@mux/mux-player": "3.6.1", @@ -2664,8 +2352,6 @@ }, "node_modules/@mux/mux-video": { "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@mux/mux-video/-/mux-video-0.27.0.tgz", - "integrity": "sha512-Oi142YAcPKrmHTG+eaWHWaE7ucMHeJwx1FXABbLM2hMGj9MQ7kYjsD5J3meFlvuyz5UeVDsPLHeUJgeBXUZovg==", "license": "MIT", "dependencies": { "@mux/mux-data-google-ima": "0.2.8", @@ -2677,8 +2363,6 @@ }, "node_modules/@mux/playback-core": { "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@mux/playback-core/-/playback-core-0.31.0.tgz", - "integrity": "sha512-VADcrtS4O6fQBH8qmgavS6h7v7amzy2oCguu1NnLaVZ3Z8WccNXcF0s7jPRoRDyXWGShgtVhypW2uXjLpkPxyw==", "license": "MIT", "dependencies": { "hls.js": "~1.6.6", @@ -2687,8 +2371,6 @@ }, "node_modules/@napi-rs/canvas": { "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas/-/canvas-0.1.80.tgz", - "integrity": "sha512-DxuT1ClnIPts1kQx8FBmkk4BQDTfI5kIzywAaMjQSXfNnra5UFU9PwurXrl+Je3bJ6BGsp/zmshVVFbCmyI+ww==", "license": "MIT", "optional": true, "workspaces": [ @@ -2710,154 +2392,8 @@ "@napi-rs/canvas-win32-x64-msvc": "0.1.80" } }, - "node_modules/@napi-rs/canvas-android-arm64": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-android-arm64/-/canvas-android-arm64-0.1.80.tgz", - "integrity": "sha512-sk7xhN/MoXeuExlggf91pNziBxLPVUqF2CAVnB57KLG/pz7+U5TKG8eXdc3pm0d7Od0WreB6ZKLj37sX9muGOQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-darwin-arm64": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-arm64/-/canvas-darwin-arm64-0.1.80.tgz", - "integrity": "sha512-O64APRTXRUiAz0P8gErkfEr3lipLJgM6pjATwavZ22ebhjYl/SUbpgM0xcWPQBNMP1n29afAC/Us5PX1vg+JNQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-darwin-x64": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-darwin-x64/-/canvas-darwin-x64-0.1.80.tgz", - "integrity": "sha512-FqqSU7qFce0Cp3pwnTjVkKjjOtxMqRe6lmINxpIZYaZNnVI0H5FtsaraZJ36SiTHNjZlUB69/HhxNDT1Aaa9vA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-linux-arm-gnueabihf": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm-gnueabihf/-/canvas-linux-arm-gnueabihf-0.1.80.tgz", - "integrity": "sha512-eyWz0ddBDQc7/JbAtY4OtZ5SpK8tR4JsCYEZjCE3dI8pqoWUC8oMwYSBGCYfsx2w47cQgQCgMVRVTFiiO38hHQ==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-linux-arm64-gnu": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-gnu/-/canvas-linux-arm64-gnu-0.1.80.tgz", - "integrity": "sha512-qwA63t8A86bnxhuA/GwOkK3jvb+XTQaTiVML0vAWoHyoZYTjNs7BzoOONDgTnNtr8/yHrq64XXzUoLqDzU+Uuw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-linux-arm64-musl": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-arm64-musl/-/canvas-linux-arm64-musl-0.1.80.tgz", - "integrity": "sha512-1XbCOz/ymhj24lFaIXtWnwv/6eFHXDrjP0jYkc6iHQ9q8oXKzUX1Lc6bu+wuGiLhGh2GS/2JlfORC5ZcXimRcg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-linux-riscv64-gnu": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-riscv64-gnu/-/canvas-linux-riscv64-gnu-0.1.80.tgz", - "integrity": "sha512-XTzR125w5ZMs0lJcxRlS1K3P5RaZ9RmUsPtd1uGt+EfDyYMu4c6SEROYsxyatbbu/2+lPe7MPHOO/0a0x7L/gw==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-linux-x64-gnu": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-gnu/-/canvas-linux-x64-gnu-0.1.80.tgz", - "integrity": "sha512-BeXAmhKg1kX3UCrJsYbdQd3hIMDH/K6HnP/pG2LuITaXhXBiNdh//TVVVVCBbJzVQaV5gK/4ZOCMrQW9mvuTqA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@napi-rs/canvas-linux-x64-musl": { - "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-linux-x64-musl/-/canvas-linux-x64-musl-0.1.80.tgz", - "integrity": "sha512-x0XvZWdHbkgdgucJsRxprX/4o4sEed7qo9rCQA9ugiS9qE2QvP0RIiEugtZhfLH3cyI+jIRFJHV4Fuz+1BHHMg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@napi-rs/canvas-win32-x64-msvc": { "version": "0.1.80", - "resolved": "https://registry.npmjs.org/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.80.tgz", - "integrity": "sha512-Z8jPsM6df5V8B1HrCHB05+bDiCxjE9QA//3YrkKIdVDEwn5RKaqOxCJDRJkl48cJbylcrJbW4HxZbTte8juuPg==", "cpu": [ "x64" ], @@ -2872,8 +2408,6 @@ }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { @@ -2886,8 +2420,6 @@ }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", "engines": { @@ -2896,8 +2428,6 @@ }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { @@ -2910,8 +2440,6 @@ }, "node_modules/@npmcli/fs": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "license": "ISC", "dependencies": { @@ -2924,8 +2452,6 @@ }, "node_modules/@npmcli/fs/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -2937,9 +2463,6 @@ }, "node_modules/@npmcli/move-file": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, "license": "MIT", "dependencies": { @@ -2952,8 +2475,6 @@ }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, "license": "MIT", "optional": true, @@ -2963,20 +2484,14 @@ }, "node_modules/@radix-ui/number": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", - "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", "license": "MIT" }, "node_modules/@radix-ui/primitive": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", - "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, "node_modules/@radix-ui/react-accordion": { "version": "1.2.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", - "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3006,8 +2521,6 @@ }, "node_modules/@radix-ui/react-arrow": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", - "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3" @@ -3029,8 +2542,6 @@ }, "node_modules/@radix-ui/react-checkbox": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.3.3.tgz", - "integrity": "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3059,8 +2570,6 @@ }, "node_modules/@radix-ui/react-collapsible": { "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", - "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3089,8 +2598,6 @@ }, "node_modules/@radix-ui/react-collection": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", - "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", @@ -3115,8 +2622,6 @@ }, "node_modules/@radix-ui/react-compose-refs": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", - "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3130,8 +2635,6 @@ }, "node_modules/@radix-ui/react-context": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", - "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3145,8 +2648,6 @@ }, "node_modules/@radix-ui/react-dialog": { "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", - "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3181,8 +2682,6 @@ }, "node_modules/@radix-ui/react-direction": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", - "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3196,8 +2695,6 @@ }, "node_modules/@radix-ui/react-dismissable-layer": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", - "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3223,8 +2720,6 @@ }, "node_modules/@radix-ui/react-dropdown-menu": { "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", - "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3252,8 +2747,6 @@ }, "node_modules/@radix-ui/react-focus-guards": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", - "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3267,8 +2760,6 @@ }, "node_modules/@radix-ui/react-focus-scope": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", - "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", @@ -3292,8 +2783,6 @@ }, "node_modules/@radix-ui/react-id": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", - "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -3310,8 +2799,6 @@ }, "node_modules/@radix-ui/react-label": { "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.7.tgz", - "integrity": "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3" @@ -3333,8 +2820,6 @@ }, "node_modules/@radix-ui/react-menu": { "version": "2.1.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", - "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3373,8 +2858,6 @@ }, "node_modules/@radix-ui/react-popover": { "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", - "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3410,8 +2893,6 @@ }, "node_modules/@radix-ui/react-popper": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", - "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", @@ -3442,8 +2923,6 @@ }, "node_modules/@radix-ui/react-portal": { "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", - "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3", @@ -3466,8 +2945,6 @@ }, "node_modules/@radix-ui/react-presence": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", - "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", @@ -3490,8 +2967,6 @@ }, "node_modules/@radix-ui/react-primitive": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", - "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", "license": "MIT", "dependencies": { "@radix-ui/react-slot": "1.2.3" @@ -3513,8 +2988,6 @@ }, "node_modules/@radix-ui/react-progress": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz", - "integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==", "license": "MIT", "dependencies": { "@radix-ui/react-context": "1.1.2", @@ -3537,8 +3010,6 @@ }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", - "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3568,8 +3039,6 @@ }, "node_modules/@radix-ui/react-scroll-area": { "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", - "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.1", @@ -3599,8 +3068,6 @@ }, "node_modules/@radix-ui/react-select": { "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.6.tgz", - "integrity": "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.1", @@ -3642,8 +3109,6 @@ }, "node_modules/@radix-ui/react-separator": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.7.tgz", - "integrity": "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3" @@ -3665,8 +3130,6 @@ }, "node_modules/@radix-ui/react-slot": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", - "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", "license": "MIT", "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" @@ -3683,8 +3146,6 @@ }, "node_modules/@radix-ui/react-switch": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.2.6.tgz", - "integrity": "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3712,8 +3173,6 @@ }, "node_modules/@radix-ui/react-tabs": { "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz", - "integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3742,8 +3201,6 @@ }, "node_modules/@radix-ui/react-tooltip": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", - "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.3", @@ -3776,8 +3233,6 @@ }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", - "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3791,8 +3246,6 @@ }, "node_modules/@radix-ui/react-use-controllable-state": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", - "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", "license": "MIT", "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", @@ -3810,8 +3263,6 @@ }, "node_modules/@radix-ui/react-use-effect-event": { "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", - "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -3828,8 +3279,6 @@ }, "node_modules/@radix-ui/react-use-escape-keydown": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", - "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", "license": "MIT", "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" @@ -3846,8 +3295,6 @@ }, "node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", - "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3861,8 +3308,6 @@ }, "node_modules/@radix-ui/react-use-previous": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", - "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -3876,8 +3321,6 @@ }, "node_modules/@radix-ui/react-use-rect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", - "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", "license": "MIT", "dependencies": { "@radix-ui/rect": "1.1.1" @@ -3894,8 +3337,6 @@ }, "node_modules/@radix-ui/react-use-size": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", - "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", "license": "MIT", "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" @@ -3912,8 +3353,6 @@ }, "node_modules/@radix-ui/react-visually-hidden": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", - "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3" @@ -3935,14 +3374,36 @@ }, "node_modules/@radix-ui/rect": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", - "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", "license": "MIT" }, + "node_modules/@reduxjs/toolkit": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.9.0.tgz", + "integrity": "sha512-fSfQlSRu9Z5yBkvsNhYF2rPS8cGXn/TZVrlwN1948QyZ8xMZ0JvP50S2acZNaf+o63u6aEeMjipFyksjIcWrog==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@replit/codemirror-lang-nix": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-nix/-/codemirror-lang-nix-6.0.1.tgz", - "integrity": "sha512-lvzjoYn9nfJzBD5qdm3Ut6G3+Or2wEacYIDJ49h9+19WSChVnxv4ojf+rNmQ78ncuxIt/bfbMvDLMeMP0xze6g==", "license": "MIT", "peerDependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -3956,8 +3417,6 @@ }, "node_modules/@replit/codemirror-lang-solidity": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-solidity/-/codemirror-lang-solidity-6.0.2.tgz", - "integrity": "sha512-/dpTVH338KFV6SaDYYSadkB4bI/0B0QRF/bkt1XS3t3QtyR49mn6+2k0OUQhvt2ZSO7kt10J+OPilRAtgbmX0w==", "license": "MIT", "dependencies": { "@lezer/highlight": "^1.2.0" @@ -3968,8 +3427,6 @@ }, "node_modules/@replit/codemirror-lang-svelte": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@replit/codemirror-lang-svelte/-/codemirror-lang-svelte-6.0.0.tgz", - "integrity": "sha512-U2OqqgMM6jKelL0GNWbAmqlu1S078zZNoBqlJBW+retTc5M4Mha6/Y2cf4SVg6ddgloJvmcSpt4hHrVoM4ePRA==", "license": "MIT", "peerDependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -3987,275 +3444,11 @@ }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", "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", - "integrity": "sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.3.tgz", - "integrity": "sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.3.tgz", - "integrity": "sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.3.tgz", - "integrity": "sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.3.tgz", - "integrity": "sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.3.tgz", - "integrity": "sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.3.tgz", - "integrity": "sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.3.tgz", - "integrity": "sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.3.tgz", - "integrity": "sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.3.tgz", - "integrity": "sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.3.tgz", - "integrity": "sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.3.tgz", - "integrity": "sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.3.tgz", - "integrity": "sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.3.tgz", - "integrity": "sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.3.tgz", - "integrity": "sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.3.tgz", - "integrity": "sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.3.tgz", - "integrity": "sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.3.tgz", - "integrity": "sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.3.tgz", - "integrity": "sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.3.tgz", - "integrity": "sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@rollup/rollup-win32-x64-gnu": { "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.3.tgz", - "integrity": "sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==", "cpu": [ "x64" ], @@ -4267,8 +3460,6 @@ }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.52.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.3.tgz", - "integrity": "sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==", "cpu": [ "x64" ], @@ -4280,8 +3471,6 @@ }, "node_modules/@sindresorhus/is": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "dev": true, "license": "MIT", "engines": { @@ -4293,26 +3482,18 @@ }, "node_modules/@standard-schema/spec": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", "license": "MIT" }, "node_modules/@standard-schema/utils": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", "license": "MIT" }, "node_modules/@svta/common-media-library": { "version": "0.12.4", - "resolved": "https://registry.npmjs.org/@svta/common-media-library/-/common-media-library-0.12.4.tgz", - "integrity": "sha512-9EuOoaNmz7JrfGwjsrD9SxF9otU5TNMnbLu1yU4BeLK0W5cDxVXXR58Z89q9u2AnHjIctscjMTYdlqQ1gojTuw==", "license": "Apache-2.0" }, "node_modules/@swc/core": { "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz", - "integrity": "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -4348,163 +3529,8 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.5.tgz", - "integrity": "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.5.tgz", - "integrity": "sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.5.tgz", - "integrity": "sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.5.tgz", - "integrity": "sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.5.tgz", - "integrity": "sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.5.tgz", - "integrity": "sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.5.tgz", - "integrity": "sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.5.tgz", - "integrity": "sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.5.tgz", - "integrity": "sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-win32-x64-msvc": { "version": "1.13.5", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.5.tgz", - "integrity": "sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==", "cpu": [ "x64" ], @@ -4520,15 +3546,11 @@ }, "node_modules/@swc/counter": { "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "dev": true, "license": "Apache-2.0" }, "node_modules/@swc/types": { "version": "0.1.25", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", - "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4537,8 +3559,6 @@ }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", "dev": true, "license": "MIT", "dependencies": { @@ -4812,8 +3832,6 @@ }, "node_modules/@tootallnate/once": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, "license": "MIT", "engines": { @@ -4822,24 +3840,19 @@ }, "node_modules/@types/bcryptjs": { "version": "2.4.6", - "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.6.tgz", - "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", "license": "MIT" }, "node_modules/@types/better-sqlite3": { "version": "7.6.13", - "resolved": "https://registry.npmjs.org/@types/better-sqlite3/-/better-sqlite3-7.6.13.tgz", - "integrity": "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/body-parser": { "version": "1.19.6", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", - "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "license": "MIT", "dependencies": { "@types/connect": "*", @@ -4848,8 +3861,6 @@ }, "node_modules/@types/cacheable-request": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", "dev": true, "license": "MIT", "dependencies": { @@ -4861,8 +3872,14 @@ }, "node_modules/@types/connect": { "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.1", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -4870,8 +3887,6 @@ }, "node_modules/@types/cookie-parser": { "version": "1.4.9", - "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", - "integrity": "sha512-tGZiZ2Gtc4m3wIdLkZ8mkj1T6CEHb35+VApbL2T14Dew8HA7c+04dmKqsKRNC+8RJPm16JEK0tFSwdZqubfc4g==", "license": "MIT", "peerDependencies": { "@types/express": "*" @@ -4879,18 +3894,77 @@ }, "node_modules/@types/cors": { "version": "2.8.19", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", - "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" } }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, "node_modules/@types/debug": { "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "license": "MIT", "dependencies": { "@types/ms": "*" @@ -4898,14 +3972,10 @@ }, "node_modules/@types/estree": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/estree-jsx": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", "license": "MIT", "dependencies": { "@types/estree": "*" @@ -4913,9 +3983,8 @@ }, "node_modules/@types/express": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", - "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", "license": "MIT", + "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", @@ -4924,8 +3993,6 @@ }, "node_modules/@types/express-serve-static-core": { "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz", - "integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==", "license": "MIT", "dependencies": { "@types/node": "*", @@ -4936,8 +4003,6 @@ }, "node_modules/@types/fs-extra": { "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, "license": "MIT", "dependencies": { @@ -4946,8 +4011,6 @@ }, "node_modules/@types/hast": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -4955,28 +4018,20 @@ }, "node_modules/@types/http-cache-semantics": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "dev": true, "license": "MIT" }, "node_modules/@types/http-errors": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", - "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/jsonwebtoken": { "version": "9.0.10", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", - "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", "dev": true, "license": "MIT", "dependencies": { @@ -4986,8 +4041,6 @@ }, "node_modules/@types/jszip": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@types/jszip/-/jszip-3.4.0.tgz", - "integrity": "sha512-GFHqtQQP3R4NNuvZH3hNCYD0NbyBZ42bkN7kO3NDrU/SnvIZWMS8Bp38XCsRKBT5BXvgm0y1zqpZWp/ZkRzBzg==", "license": "MIT", "dependencies": { "jszip": "*" @@ -4995,8 +4048,6 @@ }, "node_modules/@types/keyv": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", "dev": true, "license": "MIT", "dependencies": { @@ -5005,8 +4056,6 @@ }, "node_modules/@types/mdast": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "license": "MIT", "dependencies": { "@types/unist": "*" @@ -5014,20 +4063,14 @@ }, "node_modules/@types/mime": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "license": "MIT" }, "node_modules/@types/ms": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", "license": "MIT" }, "node_modules/@types/multer": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz", - "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==", "license": "MIT", "dependencies": { "@types/express": "*" @@ -5035,29 +4078,14 @@ }, "node_modules/@types/node": { "version": "24.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.6.1.tgz", - "integrity": "sha512-ljvjjs3DNXummeIaooB4cLBKg2U6SPI6Hjra/9rRIy7CpM0HpLtG9HptkMKAb4HYWy5S7HUvJEuWgr/y0U8SHw==", "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.13.0" } }, - "node_modules/@types/plist": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", - "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*", - "xmlbuilder": ">=11.0.1" - } - }, "node_modules/@types/qrcode": { "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@types/qrcode/-/qrcode-1.5.5.tgz", - "integrity": "sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5065,39 +4093,31 @@ }, "node_modules/@types/qs": { "version": "6.14.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==", "license": "MIT" }, "node_modules/@types/range-parser": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", "license": "MIT" }, "node_modules/@types/react": { "version": "19.1.17", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.17.tgz", - "integrity": "sha512-Qec1E3mhALmaspIrhWt9jkQMNdw6bReVu64mjvhbhq2NFPftLPVr+l1SZgmw/66WwBNpDh7ao5AT6gF5v41PFA==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { "version": "19.1.11", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.11.tgz", - "integrity": "sha512-3BKc/yGdNTYQVVw4idqHtSOcFsgGuBbMveKCOgF8wQ5QtrYOc3jDIlzg3jef04zcXFIHLelyGlj0T+BJ8+KN+w==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.0.0" } }, "node_modules/@types/responselike": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", "dev": true, "license": "MIT", "dependencies": { @@ -5106,8 +4126,6 @@ }, "node_modules/@types/send": { "version": "0.17.5", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", - "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", "license": "MIT", "dependencies": { "@types/mime": "^1", @@ -5116,8 +4134,6 @@ }, "node_modules/@types/serve-static": { "version": "1.15.8", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", - "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", "license": "MIT", "dependencies": { "@types/http-errors": "*", @@ -5127,8 +4143,6 @@ }, "node_modules/@types/speakeasy": { "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@types/speakeasy/-/speakeasy-2.0.10.tgz", - "integrity": "sha512-QVRlDW5r4yl7p7xkNIbAIC/JtyOcClDIIdKfuG7PWdDT1MmyhtXSANsildohy0K+Lmvf/9RUtLbNLMacvrVwxA==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -5136,8 +4150,6 @@ }, "node_modules/@types/ssh2": { "version": "1.15.5", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.5.tgz", - "integrity": "sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5146,8 +4158,6 @@ }, "node_modules/@types/ssh2/node_modules/@types/node": { "version": "18.19.129", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.129.tgz", - "integrity": "sha512-hrmi5jWt2w60ayox3iIXwpMEnfUvOLJCRtrOPbHtH15nTjvO7uhnelvrdAs0dO0/zl5DZ3ZbahiaXEVb54ca/A==", "dev": true, "license": "MIT", "dependencies": { @@ -5156,36 +4166,25 @@ }, "node_modules/@types/ssh2/node_modules/undici-types": { "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, "license": "MIT" }, "node_modules/@types/trusted-types": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-1.0.6.tgz", - "integrity": "sha512-230RC8sFeHoT6sSUlRO6a8cAnclO06eeiq1QDfiv2FGCLWFvvERWgwIQD4FWqD9A69BN7Lzee4OXwoMVnnsWDw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/unist": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, - "node_modules/@types/verror": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", - "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", - "dev": true, - "license": "MIT", - "optional": true + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" }, "node_modules/@types/ws": { "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", "dev": true, "license": "MIT", "dependencies": { @@ -5194,8 +4193,6 @@ }, "node_modules/@types/yauzl": { "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, "license": "MIT", "optional": true, @@ -5205,8 +4202,6 @@ }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz", - "integrity": "sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg==", "dev": true, "license": "MIT", "dependencies": { @@ -5235,8 +4230,6 @@ }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", "engines": { @@ -5245,10 +4238,9 @@ }, "node_modules/@typescript-eslint/parser": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.45.0.tgz", - "integrity": "sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.45.0", "@typescript-eslint/types": "8.45.0", @@ -5270,8 +4262,6 @@ }, "node_modules/@typescript-eslint/parser/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": { @@ -5288,15 +4278,11 @@ }, "node_modules/@typescript-eslint/parser/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/@typescript-eslint/project-service": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.45.0.tgz", - "integrity": "sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg==", "dev": true, "license": "MIT", "dependencies": { @@ -5317,8 +4303,6 @@ }, "node_modules/@typescript-eslint/project-service/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": { @@ -5335,15 +4319,11 @@ }, "node_modules/@typescript-eslint/project-service/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/@typescript-eslint/scope-manager": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz", - "integrity": "sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA==", "dev": true, "license": "MIT", "dependencies": { @@ -5360,8 +4340,6 @@ }, "node_modules/@typescript-eslint/tsconfig-utils": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.45.0.tgz", - "integrity": "sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w==", "dev": true, "license": "MIT", "engines": { @@ -5377,8 +4355,6 @@ }, "node_modules/@typescript-eslint/type-utils": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.45.0.tgz", - "integrity": "sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A==", "dev": true, "license": "MIT", "dependencies": { @@ -5402,8 +4378,6 @@ }, "node_modules/@typescript-eslint/type-utils/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": { @@ -5420,15 +4394,11 @@ }, "node_modules/@typescript-eslint/type-utils/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/@typescript-eslint/types": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.45.0.tgz", - "integrity": "sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA==", "dev": true, "license": "MIT", "engines": { @@ -5441,8 +4411,6 @@ }, "node_modules/@typescript-eslint/typescript-estree": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz", - "integrity": "sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA==", "dev": true, "license": "MIT", "dependencies": { @@ -5470,8 +4438,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5480,8 +4446,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/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": { @@ -5498,8 +4462,6 @@ }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { @@ -5514,15 +4476,11 @@ }, "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -5534,8 +4492,6 @@ }, "node_modules/@typescript-eslint/utils": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.45.0.tgz", - "integrity": "sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg==", "dev": true, "license": "MIT", "dependencies": { @@ -5558,8 +4514,6 @@ }, "node_modules/@typescript-eslint/visitor-keys": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz", - "integrity": "sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag==", "dev": true, "license": "MIT", "dependencies": { @@ -5576,8 +4530,6 @@ }, "node_modules/@uiw/codemirror-extensions-basic-setup": { "version": "4.25.2", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-basic-setup/-/codemirror-extensions-basic-setup-4.25.2.tgz", - "integrity": "sha512-s2fbpdXrSMWEc86moll/d007ZFhu6jzwNu5cWv/2o7egymvLeZO52LWkewgbr+BUCGWGPsoJVWeaejbsb/hLcw==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -5603,8 +4555,6 @@ }, "node_modules/@uiw/codemirror-extensions-langs": { "version": "4.25.2", - "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-langs/-/codemirror-extensions-langs-4.25.2.tgz", - "integrity": "sha512-fWS9fP52QJAFgXbsUl6vKMBqQ2PIT8z5TvX8BKBqPz/I+ayh6Fk+HzoeUtslUGPTu+UTPgB5m0qt3rTIDXWvng==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -5624,8 +4574,6 @@ }, "node_modules/@uiw/react-codemirror": { "version": "4.25.2", - "resolved": "https://registry.npmjs.org/@uiw/react-codemirror/-/react-codemirror-4.25.2.tgz", - "integrity": "sha512-XP3R1xyE0CP6Q0iR0xf3ed+cJzJnfmbLelgJR6osVVtMStGGZP3pGQjjwDRYptmjGHfEELUyyBLdY25h0BQg7w==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.18.6", @@ -5650,14 +4598,10 @@ }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, "node_modules/@vimeo/player": { "version": "2.29.0", - "resolved": "https://registry.npmjs.org/@vimeo/player/-/player-2.29.0.tgz", - "integrity": "sha512-9JjvjeqUndb9otCCFd0/+2ESsLk7VkDE6sxOBy9iy2ukezuQbplVRi+g9g59yAurKofbmTi/KcKxBGO/22zWRw==", "license": "MIT", "dependencies": { "native-promise-only": "0.8.1", @@ -5666,8 +4610,6 @@ }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.11.0.tgz", - "integrity": "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w==", "dev": true, "license": "MIT", "dependencies": { @@ -5680,8 +4622,6 @@ }, "node_modules/@xmldom/xmldom": { "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", "dev": true, "license": "MIT", "engines": { @@ -5690,8 +4630,6 @@ }, "node_modules/@xterm/addon-clipboard": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-clipboard/-/addon-clipboard-0.1.0.tgz", - "integrity": "sha512-zdoM7p53T5sv/HbRTyp4hY0kKmEQ3MZvAvEtiXqNIHc/JdpqwByCtsTaQF5DX2n4hYdXRPO4P/eOS0QEhX1nPw==", "license": "MIT", "dependencies": { "js-base64": "^3.7.5" @@ -5702,8 +4640,6 @@ }, "node_modules/@xterm/addon-fit": { "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz", - "integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==", "license": "MIT", "peerDependencies": { "@xterm/xterm": "^5.0.0" @@ -5711,8 +4647,6 @@ }, "node_modules/@xterm/addon-unicode11": { "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-unicode11/-/addon-unicode11-0.8.0.tgz", - "integrity": "sha512-LxinXu8SC4OmVa6FhgwsVCBZbr8WoSGzBl2+vqe8WcQ6hb1r6Gj9P99qTNdPiFPh4Ceiu2pC8xukZ6+2nnh49Q==", "license": "MIT", "peerDependencies": { "@xterm/xterm": "^5.0.0" @@ -5720,8 +4654,6 @@ }, "node_modules/@xterm/addon-web-links": { "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@xterm/addon-web-links/-/addon-web-links-0.11.0.tgz", - "integrity": "sha512-nIHQ38pQI+a5kXnRaTgwqSHnX7KE6+4SVoceompgHL26unAxdfP6IPqUTSYPQgSwM56hsElfoNrrW5V7BUED/Q==", "license": "MIT", "peerDependencies": { "@xterm/xterm": "^5.0.0" @@ -5729,28 +4661,21 @@ }, "node_modules/@xterm/xterm": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", - "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/7zip-bin": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", - "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", "dev": true, "license": "MIT" }, "node_modules/abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "license": "ISC" }, "node_modules/accepts": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "license": "MIT", "dependencies": { "mime-types": "^3.0.0", @@ -5762,10 +4687,9 @@ }, "node_modules/acorn": { "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5775,8 +4699,6 @@ }, "node_modules/acorn-jsx": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -5785,8 +4707,6 @@ }, "node_modules/agent-base": { "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", "engines": { @@ -5795,8 +4715,6 @@ }, "node_modules/agentkeepalive": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5808,8 +4726,6 @@ }, "node_modules/aggregate-error": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "license": "MIT", "dependencies": { @@ -5822,10 +4738,9 @@ }, "node_modules/ajv": { "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5839,18 +4754,28 @@ }, "node_modules/ajv-keywords": { "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } }, + "node_modules/ansi-escapes": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { "node": ">=8" @@ -5858,8 +4783,6 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -5873,15 +4796,11 @@ }, "node_modules/app-builder-bin": { "version": "5.0.0-alpha.12", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz", - "integrity": "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==", "dev": true, "license": "MIT" }, "node_modules/app-builder-lib": { "version": "26.0.12", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.0.12.tgz", - "integrity": "sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==", "dev": true, "license": "MIT", "dependencies": { @@ -5929,8 +4848,6 @@ }, "node_modules/app-builder-lib/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": { @@ -5947,8 +4864,6 @@ }, "node_modules/app-builder-lib/node_modules/dotenv": { "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -5960,8 +4875,6 @@ }, "node_modules/app-builder-lib/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5975,8 +4888,6 @@ }, "node_modules/app-builder-lib/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -5988,8 +4899,6 @@ }, "node_modules/app-builder-lib/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "license": "ISC", "engines": { @@ -5998,15 +4907,11 @@ }, "node_modules/app-builder-lib/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/app-builder-lib/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -6018,8 +4923,6 @@ }, "node_modules/app-builder-lib/node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "license": "ISC", "dependencies": { @@ -6036,8 +4939,6 @@ }, "node_modules/app-builder-lib/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -6046,21 +4947,15 @@ }, "node_modules/append-field": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/aria-hidden": { "version": "1.2.6", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", - "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -6069,48 +4964,25 @@ "node": ">=10" } }, + "node_modules/array-ify": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/asn1": { "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", "license": "MIT", "dependencies": { "safer-buffer": "~2.1.0" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/async": { "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "dev": true, "license": "MIT" }, "node_modules/async-exit-hook": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true, "license": "MIT", "engines": { @@ -6119,14 +4991,10 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, "license": "ISC", "engines": { @@ -6135,8 +5003,6 @@ }, "node_modules/axios": { "version": "1.12.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", - "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -6146,8 +5012,6 @@ }, "node_modules/bail": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "license": "MIT", "funding": { "type": "github", @@ -6156,21 +5020,15 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/base32.js": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.0.1.tgz", - "integrity": "sha512-EGHIRiegFa62/SsA1J+Xs2tIzludPdzM064N9wjbiEgHnGnJ1V0WEpA4pEwCYT5nDvZk3ubf0shqaCS7k6xeUQ==", "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "funding": [ { "type": "github", @@ -6189,8 +5047,6 @@ }, "node_modules/bcp-47": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", - "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", "license": "MIT", "dependencies": { "is-alphabetical": "^2.0.0", @@ -6204,8 +5060,6 @@ }, "node_modules/bcp-47-match": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", - "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", "license": "MIT", "funding": { "type": "github", @@ -6214,8 +5068,6 @@ }, "node_modules/bcp-47-normalize": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", - "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", "license": "MIT", "dependencies": { "bcp-47": "^2.0.0", @@ -6228,8 +5080,6 @@ }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", "license": "BSD-3-Clause", "dependencies": { "tweetnacl": "^0.14.3" @@ -6237,8 +5087,6 @@ }, "node_modules/bcryptjs": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-3.0.2.tgz", - "integrity": "sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==", "license": "BSD-3-Clause", "bin": { "bcrypt": "bin/bcrypt" @@ -6246,10 +5094,9 @@ }, "node_modules/better-sqlite3": { "version": "12.4.1", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.4.1.tgz", - "integrity": "sha512-3yVdyZhklTiNrtg+4WqHpJpFDd+WHTg2oM7UcR80GqL05AOV0xEJzc6qNvFYoEtE+hRp1n9MpN6/+4yhlGkDXQ==", "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" @@ -6260,8 +5107,6 @@ }, "node_modules/bindings": { "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "license": "MIT", "dependencies": { "file-uri-to-path": "1.0.0" @@ -6269,8 +5114,6 @@ }, "node_modules/bl": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { "buffer": "^5.5.0", @@ -6280,8 +5123,6 @@ }, "node_modules/bl/node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -6294,8 +5135,6 @@ }, "node_modules/body-parser": { "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -6318,17 +5157,12 @@ }, "node_modules/boolean": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "license": "MIT", "optional": true }, "node_modules/brace-expansion": { "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -6338,8 +5172,6 @@ }, "node_modules/braces": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { @@ -6351,8 +5183,6 @@ }, "node_modules/buffer": { "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -6375,8 +5205,6 @@ }, "node_modules/buffer-crc32": { "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "license": "MIT", "engines": { @@ -6385,29 +5213,14 @@ }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", "license": "BSD-3-Clause" }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "license": "MIT" }, - "node_modules/buildcheck": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", - "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", - "optional": true, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/builder-util": { "version": "26.0.11", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.0.11.tgz", - "integrity": "sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==", "dev": true, "license": "MIT", "dependencies": { @@ -6432,8 +5245,6 @@ }, "node_modules/builder-util-runtime": { "version": "9.3.1", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz", - "integrity": "sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6446,8 +5257,6 @@ }, "node_modules/builder-util-runtime/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": { @@ -6464,15 +5273,11 @@ }, "node_modules/builder-util-runtime/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/builder-util/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": { @@ -6489,8 +5294,6 @@ }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6504,8 +5307,6 @@ }, "node_modules/builder-util/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -6517,15 +5318,11 @@ }, "node_modules/builder-util/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/builder-util/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -6534,8 +5331,6 @@ }, "node_modules/busboy": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dependencies": { "streamsearch": "^1.1.0" }, @@ -6545,8 +5340,6 @@ }, "node_modules/bytes": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -6554,8 +5347,6 @@ }, "node_modules/cacache": { "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6584,8 +5375,6 @@ }, "node_modules/cacache/node_modules/brace-expansion": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6594,9 +5383,6 @@ }, "node_modules/cacache/node_modules/glob": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -6615,8 +5401,6 @@ }, "node_modules/cacache/node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "license": "ISC", "engines": { @@ -6625,8 +5409,6 @@ }, "node_modules/cacache/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", "dependencies": { @@ -6638,8 +5420,6 @@ }, "node_modules/cacache/node_modules/tar": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "license": "ISC", "dependencies": { @@ -6656,8 +5436,6 @@ }, "node_modules/cacache/node_modules/tar/node_modules/minipass": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "license": "ISC", "engines": { @@ -6666,8 +5444,6 @@ }, "node_modules/cacheable-lookup": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", "dev": true, "license": "MIT", "engines": { @@ -6676,8 +5452,6 @@ }, "node_modules/cacheable-request": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", "dev": true, "license": "MIT", "dependencies": { @@ -6695,8 +5469,6 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -6708,8 +5480,6 @@ }, "node_modules/call-bound": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -6724,8 +5494,6 @@ }, "node_modules/callsites": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { @@ -6734,8 +5502,6 @@ }, "node_modules/camelcase": { "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "license": "MIT", "engines": { "node": ">=6" @@ -6743,8 +5509,6 @@ }, "node_modules/castable-video": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/castable-video/-/castable-video-1.1.11.tgz", - "integrity": "sha512-LCRTK6oe7SB1SiUQFzZCo6D6gcEzijqBTVIuj3smKpQdesXM18QTbCVqWgh9MfOeQgTx/i9ji5jGcdqNPeWg2g==", "license": "MIT", "dependencies": { "custom-media-element": "~1.4.5" @@ -6752,8 +5516,6 @@ }, "node_modules/ccount": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", "license": "MIT", "funding": { "type": "github", @@ -6762,8 +5524,6 @@ }, "node_modules/ce-la-react": { "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ce-la-react/-/ce-la-react-0.3.1.tgz", - "integrity": "sha512-g0YwpZDPIwTwFumGTzNHcgJA6VhFfFCJkSNdUdC04br2UfU+56JDrJrJva3FZ7MToB4NDHAFBiPE/PZdNl1mQA==", "license": "BSD-3-Clause", "peerDependencies": { "react": ">=17.0.0" @@ -6771,8 +5531,6 @@ }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", @@ -6787,8 +5545,6 @@ }, "node_modules/character-entities": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", "license": "MIT", "funding": { "type": "github", @@ -6797,8 +5553,6 @@ }, "node_modules/character-entities-html4": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", "license": "MIT", "funding": { "type": "github", @@ -6807,8 +5561,6 @@ }, "node_modules/character-entities-legacy": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "license": "MIT", "funding": { "type": "github", @@ -6817,8 +5569,6 @@ }, "node_modules/character-reference-invalid": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", "license": "MIT", "funding": { "type": "github", @@ -6827,8 +5577,6 @@ }, "node_modules/chownr": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "license": "ISC", "engines": { @@ -6837,15 +5585,11 @@ }, "node_modules/chromium-pickle-js": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", "dev": true, "license": "MIT" }, "node_modules/ci-info": { "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -6860,8 +5604,6 @@ }, "node_modules/class-variance-authority": { "version": "0.7.1", - "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", - "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", "license": "Apache-2.0", "dependencies": { "clsx": "^2.1.1" @@ -6872,8 +5614,6 @@ }, "node_modules/clean-stack": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "license": "MIT", "engines": { @@ -6882,8 +5622,6 @@ }, "node_modules/cli-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", "dependencies": { @@ -6895,8 +5633,6 @@ }, "node_modules/cli-spinners": { "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", "engines": { @@ -6906,28 +5642,8 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6941,8 +5657,6 @@ }, "node_modules/clone": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, "license": "MIT", "engines": { @@ -6951,8 +5665,6 @@ }, "node_modules/clone-response": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dev": true, "license": "MIT", "dependencies": { @@ -6964,14 +5676,10 @@ }, "node_modules/cloudflare-video-element": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/cloudflare-video-element/-/cloudflare-video-element-1.3.4.tgz", - "integrity": "sha512-F9g+tXzGEXI6v6L48qXxr8vnR8+L6yy7IhpJxK++lpzuVekMHTixxH7/dzLuq6OacVGziU4RB5pzZYJ7/LYtJg==", "license": "MIT" }, "node_modules/clsx": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", "license": "MIT", "engines": { "node": ">=6" @@ -6979,14 +5687,10 @@ }, "node_modules/codem-isoboxer": { "version": "0.3.10", - "resolved": "https://registry.npmjs.org/codem-isoboxer/-/codem-isoboxer-0.3.10.tgz", - "integrity": "sha512-eNk3TRV+xQMJ1PEj0FQGY8KD4m0GPxT487XJ+Iftm7mVa9WpPFDMWqPt+46buiP5j5Wzqe5oMIhqBcAeKfygSA==", "license": "MIT" }, "node_modules/codemirror": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", - "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", "license": "MIT", "dependencies": { "@codemirror/autocomplete": "^6.0.0", @@ -7000,8 +5704,6 @@ }, "node_modules/codemirror-lang-mermaid": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/codemirror-lang-mermaid/-/codemirror-lang-mermaid-0.5.0.tgz", - "integrity": "sha512-Taw/2gPCyNArQJCxIP/HSUif+3zrvD+6Ugt7KJZ2dUKou/8r3ZhcfG8krNTZfV2iu8AuGnymKuo7bLPFyqsh/A==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.9.0", @@ -7011,8 +5713,6 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -7023,14 +5723,15 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -7041,8 +5742,6 @@ }, "node_modules/comma-separated-tokens": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "license": "MIT", "funding": { "type": "github", @@ -7051,18 +5750,23 @@ }, "node_modules/commander": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, "license": "MIT", "engines": { "node": ">= 6" } }, + "node_modules/compare-func": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, "node_modules/compare-version": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", "dev": true, "license": "MIT", "engines": { @@ -7071,15 +5775,11 @@ }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/concat-stream": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "engines": [ "node >= 6.0" ], @@ -7093,8 +5793,6 @@ }, "node_modules/concat-stream/node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -7107,8 +5805,6 @@ }, "node_modules/concurrently": { "version": "9.2.1", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-9.2.1.tgz", - "integrity": "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng==", "dev": true, "license": "MIT", "dependencies": { @@ -7132,8 +5828,6 @@ }, "node_modules/concurrently/node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { @@ -7148,8 +5842,6 @@ }, "node_modules/config-file-ts": { "version": "0.2.8-rc1", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", - "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", "dev": true, "license": "MIT", "dependencies": { @@ -7159,8 +5851,6 @@ }, "node_modules/config-file-ts/node_modules/brace-expansion": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7169,8 +5859,6 @@ }, "node_modules/config-file-ts/node_modules/glob": { "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, "license": "ISC", "dependencies": { @@ -7190,8 +5878,6 @@ }, "node_modules/config-file-ts/node_modules/minimatch": { "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "license": "ISC", "dependencies": { @@ -7206,8 +5892,6 @@ }, "node_modules/config-file-ts/node_modules/minipass": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "license": "ISC", "engines": { @@ -7216,8 +5900,6 @@ }, "node_modules/content-disposition": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" @@ -7228,17 +5910,52 @@ }, "node_modules/content-type": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^2.0.0", + "JSONStream": "^1.3.5", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/cookie": { "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -7246,8 +5963,6 @@ }, "node_modules/cookie-parser": { "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", "license": "MIT", "dependencies": { "cookie": "0.7.2", @@ -7259,20 +5974,14 @@ }, "node_modules/cookie-signature": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, "node_modules/core-util-is": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", "dependencies": { "object-assign": "^4", @@ -7282,50 +5991,60 @@ "node": ">= 0.10" } }, - "node_modules/cpu-features": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", - "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", - "hasInstallScript": true, - "optional": true, - "dependencies": { - "buildcheck": "~0.0.6", - "nan": "^2.19.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "node_modules/cosmiconfig": { + "version": "9.0.0", "dev": true, "license": "MIT", - "optional": true, + "peer": true, "dependencies": { - "buffer": "^5.1.0" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "^2.4.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" } }, "node_modules/crelt": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", - "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "license": "MIT" }, "node_modules/cross-dirname": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", - "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", "dev": true, "license": "MIT", - "optional": true, - "peer": true + "optional": true }, "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": { @@ -7339,20 +6058,146 @@ }, "node_modules/csstype": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "license": "MIT" }, "node_modules/custom-media-element": { "version": "1.4.5", - "resolved": "https://registry.npmjs.org/custom-media-element/-/custom-media-element-1.4.5.tgz", - "integrity": "sha512-cjrsQufETwxjvwZbYbKBCJNvmQ2++G9AvT45zDi7NXL9k2PdVcs2h0jQz96J6G4TMKRCcEsoJ+QTgQD00Igtjw==", "license": "MIT" }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/dargs": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/dash-video-element": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dash-video-element/-/dash-video-element-0.2.0.tgz", - "integrity": "sha512-dgmhBOte6JgvSvowvrh0Q/vhSrB52Q/AUl/KqminAUkPuUT3CCUNhto1X8ANigWkmNwhktFc/PCe0lF/4tBFwQ==", "license": "MIT", "dependencies": { "custom-media-element": "^1.4.5", @@ -7362,8 +6207,6 @@ }, "node_modules/dashjs": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/dashjs/-/dashjs-5.0.3.tgz", - "integrity": "sha512-TXndNnCUjFjF2nYBxDVba+hWRpVkadkQ8flLp7kHkem+5+wZTfRShJCnVkPUosmjS0YPE9fVNLbYPJxHBeQZvA==", "license": "BSD-3-Clause", "dependencies": { "@svta/common-media-library": "^0.12.4", @@ -7380,8 +6223,6 @@ }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", "license": "MIT", "engines": { "node": ">= 12" @@ -7389,8 +6230,6 @@ }, "node_modules/debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { "ms": "2.0.0" @@ -7398,17 +6237,19 @@ }, "node_modules/decamelize": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, "node_modules/decode-named-character-reference": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -7420,8 +6261,6 @@ }, "node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" @@ -7435,8 +6274,6 @@ }, "node_modules/decompress-response/node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "license": "MIT", "engines": { "node": ">=10" @@ -7447,8 +6284,6 @@ }, "node_modules/deep-extend": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "license": "MIT", "engines": { "node": ">=4.0.0" @@ -7456,15 +6291,11 @@ }, "node_modules/deep-is": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/defaults": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, "license": "MIT", "dependencies": { @@ -7476,8 +6307,6 @@ }, "node_modules/defer-to-connect": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, "license": "MIT", "engines": { @@ -7486,8 +6315,6 @@ }, "node_modules/define-data-property": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "optional": true, @@ -7505,8 +6332,6 @@ }, "node_modules/define-properties": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "optional": true, @@ -7524,8 +6349,6 @@ }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" @@ -7533,8 +6356,6 @@ }, "node_modules/depd": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -7542,8 +6363,6 @@ }, "node_modules/dequal": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", "engines": { "node": ">=6" @@ -7551,8 +6370,6 @@ }, "node_modules/destroy": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", "license": "MIT", "engines": { "node": ">= 0.8", @@ -7561,8 +6378,6 @@ }, "node_modules/detect-libc": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.1.tgz", - "integrity": "sha512-ecqj/sy1jcK1uWrwpR67UhYrIFQ+5WlGxth34WquCbamhFA6hkkwiu37o6J5xCHdo1oixJRfVRw+ywV+Hq/0Aw==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -7570,22 +6385,16 @@ }, "node_modules/detect-node": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "dev": true, "license": "MIT", "optional": true }, "node_modules/detect-node-es": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", - "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", "license": "MIT" }, "node_modules/devlop": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { "dequal": "^2.0.0" @@ -7597,14 +6406,10 @@ }, "node_modules/dijkstrajs": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "license": "MIT" }, "node_modules/dir-compare": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", - "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7614,8 +6419,6 @@ }, "node_modules/dir-compare/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -7627,10 +6430,9 @@ }, "node_modules/dmg-builder": { "version": "26.0.12", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.0.12.tgz", - "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "26.0.12", "builder-util": "26.0.11", @@ -7645,8 +6447,6 @@ }, "node_modules/dmg-builder/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7660,8 +6460,6 @@ }, "node_modules/dmg-builder/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { @@ -7673,8 +6471,6 @@ }, "node_modules/dmg-builder/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -7686,36 +6482,18 @@ }, "node_modules/dmg-builder/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" } }, - "node_modules/dmg-license": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", - "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "node_modules/dot-prop": { + "version": "5.3.0", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "dependencies": { - "@types/plist": "^3.0.1", - "@types/verror": "^1.10.3", - "ajv": "^6.10.0", - "crc": "^3.8.0", - "iconv-corefoundation": "^1.1.7", - "plist": "^3.0.4", - "smart-buffer": "^4.0.2", - "verror": "^1.10.0" - }, - "bin": { - "dmg-license": "bin/dmg-license.js" + "is-obj": "^2.0.0" }, "engines": { "node": ">=8" @@ -7723,8 +6501,6 @@ }, "node_modules/dotenv": { "version": "17.2.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", - "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -7735,8 +6511,6 @@ }, "node_modules/dotenv-expand": { "version": "11.0.7", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", - "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -7751,8 +6525,6 @@ }, "node_modules/dotenv-expand/node_modules/dotenv": { "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -7764,8 +6536,6 @@ }, "node_modules/drizzle-orm": { "version": "0.44.5", - "resolved": "https://registry.npmjs.org/drizzle-orm/-/drizzle-orm-0.44.5.tgz", - "integrity": "sha512-jBe37K7d8ZSKptdKfakQFdeljtu3P2Cbo7tJoJSVZADzIKOBo9IAJPOmMsH2bZl90bZgh8FQlD8BjxXA/zuBkQ==", "license": "Apache-2.0", "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", @@ -7889,8 +6659,6 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -7903,15 +6671,11 @@ }, "node_modules/eastasianwidth": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, "license": "MIT" }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -7919,14 +6683,10 @@ }, "node_modules/ee-first": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, "node_modules/ejs": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7941,8 +6701,6 @@ }, "node_modules/electron": { "version": "38.2.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-38.2.0.tgz", - "integrity": "sha512-Cw5Mb+N5NxsG0Hc1qr8I65Kt5APRrbgTtEEn3zTod30UNJRnAE1xbGk/1NOaDn3ODzI/MYn6BzT9T9zreP7xWA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -7960,8 +6718,6 @@ }, "node_modules/electron-builder": { "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.0.12.tgz", - "integrity": "sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==", "dev": true, "license": "MIT", "dependencies": { @@ -7986,8 +6742,6 @@ }, "node_modules/electron-builder-squirrel-windows": { "version": "26.0.12", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz", - "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==", "dev": true, "license": "MIT", "peer": true, @@ -7999,8 +6753,6 @@ }, "node_modules/electron-builder/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8014,8 +6766,6 @@ }, "node_modules/electron-builder/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -8027,8 +6777,6 @@ }, "node_modules/electron-builder/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -8037,8 +6785,6 @@ }, "node_modules/electron-publish": { "version": "26.0.11", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.0.11.tgz", - "integrity": "sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==", "dev": true, "license": "MIT", "dependencies": { @@ -8054,8 +6800,6 @@ }, "node_modules/electron-publish/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8069,8 +6813,6 @@ }, "node_modules/electron-publish/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -8082,8 +6824,6 @@ }, "node_modules/electron-publish/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -8092,12 +6832,9 @@ }, "node_modules/electron-winstaller": { "version": "5.4.0", - "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", - "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", @@ -8114,11 +6851,8 @@ }, "node_modules/electron-winstaller/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", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -8133,11 +6867,8 @@ }, "node_modules/electron-winstaller/node_modules/fs-extra": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -8149,16 +6880,11 @@ }, "node_modules/electron-winstaller/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", - "peer": true + "license": "MIT" }, "node_modules/electron/node_modules/@types/node": { "version": "22.18.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.8.tgz", - "integrity": "sha512-pAZSHMiagDR7cARo/cch1f3rXy0AEXwsVsVH09FcyeJVAzCnGgmYis7P3JidtTUjyadhTeSo8TgRPswstghDaw==", "dev": true, "license": "MIT", "dependencies": { @@ -8167,21 +6893,15 @@ }, "node_modules/electron/node_modules/undici-types": { "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, "node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8189,8 +6909,6 @@ }, "node_modules/encoding": { "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "license": "MIT", "optional": true, @@ -8200,8 +6918,6 @@ }, "node_modules/encoding/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "optional": true, @@ -8214,8 +6930,6 @@ }, "node_modules/end-of-stream": { "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -8236,25 +6950,38 @@ }, "node_modules/env-paths": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/err-code": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", "dev": true, "license": "MIT" }, + "node_modules/error-ex": { + "version": "1.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -8262,8 +6989,6 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -8271,8 +6996,6 @@ }, "node_modules/es-object-atoms": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -8283,8 +7006,6 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -8296,18 +7017,24 @@ "node": ">= 0.4" } }, + "node_modules/es-toolkit": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.40.0.tgz", + "integrity": "sha512-8o6w0KFmU0CiIl0/Q/BCEOabF2IJaELM1T2PWj6e8KqzHv1gdx+7JtFnDwOx1kJH/isJ5NwlDG1nCr1HrRF94Q==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/es6-error": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", "dev": true, "license": "MIT", "optional": true }, "node_modules/esbuild": { "version": "0.25.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", - "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -8347,8 +7074,6 @@ }, "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": { @@ -8357,14 +7082,10 @@ }, "node_modules/escape-html": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { @@ -8376,10 +7097,9 @@ }, "node_modules/eslint": { "version": "9.36.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz", - "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -8437,8 +7157,6 @@ }, "node_modules/eslint-plugin-react-hooks": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", - "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "license": "MIT", "engines": { @@ -8450,8 +7168,6 @@ }, "node_modules/eslint-plugin-react-refresh": { "version": "0.4.22", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.22.tgz", - "integrity": "sha512-atkAG6QaJMGoTLc4MDAP+rqZcfwQuTIh2IqHWFLy2TEjxr0MOK+5BSG4RzL2564AAPpZkDRsZXAUz68kjnU6Ug==", "dev": true, "license": "MIT", "peerDependencies": { @@ -8460,8 +7176,6 @@ }, "node_modules/eslint-scope": { "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -8477,8 +7191,6 @@ }, "node_modules/eslint-visitor-keys": { "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -8490,8 +7202,6 @@ }, "node_modules/eslint/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": { @@ -8508,8 +7218,6 @@ }, "node_modules/eslint/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -8521,15 +7229,11 @@ }, "node_modules/eslint/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/espree": { "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -8546,8 +7250,6 @@ }, "node_modules/esquery": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -8559,8 +7261,6 @@ }, "node_modules/esrecurse": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -8572,8 +7272,6 @@ }, "node_modules/estraverse": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -8582,8 +7280,6 @@ }, "node_modules/estree-util-is-identifier-name": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", "license": "MIT", "funding": { "type": "opencollective", @@ -8592,8 +7288,6 @@ }, "node_modules/esutils": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -8602,17 +7296,17 @@ }, "node_modules/etag": { "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "license": "MIT" + }, "node_modules/expand-template": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", "license": "(MIT OR WTFPL)", "engines": { "node": ">=6" @@ -8620,15 +7314,11 @@ }, "node_modules/exponential-backoff": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", - "integrity": "sha512-8QxYTVXUkuy7fIIoitQkPwGonB8F3Zj8eEO8Sqg9Zv/bkI7RJAzowee4gr81Hak/dUTpA2Z7VfQgoijjPNlUZA==", "dev": true, "license": "Apache-2.0" }, "node_modules/express": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", - "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", "license": "MIT", "dependencies": { "accepts": "^2.0.0", @@ -8669,8 +7359,6 @@ }, "node_modules/express/node_modules/body-parser": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", @@ -8689,8 +7377,6 @@ }, "node_modules/express/node_modules/cookie-signature": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", "engines": { "node": ">=6.6.0" @@ -8698,8 +7384,6 @@ }, "node_modules/express/node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -8715,8 +7399,6 @@ }, "node_modules/express/node_modules/iconv-lite": { "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -8727,8 +7409,6 @@ }, "node_modules/express/node_modules/media-typer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -8736,14 +7416,10 @@ }, "node_modules/express/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==", "license": "MIT" }, "node_modules/express/node_modules/qs": { "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" @@ -8757,8 +7433,6 @@ }, "node_modules/express/node_modules/raw-body": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", - "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -8772,8 +7446,6 @@ }, "node_modules/express/node_modules/raw-body/node_modules/iconv-lite": { "version": "0.7.0", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", - "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -8788,8 +7460,6 @@ }, "node_modules/express/node_modules/type-is": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "license": "MIT", "dependencies": { "content-type": "^1.0.5", @@ -8802,14 +7472,10 @@ }, "node_modules/extend": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, "node_modules/extract-zip": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -8829,8 +7495,6 @@ }, "node_modules/extract-zip/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": { @@ -8847,32 +7511,15 @@ }, "node_modules/extract-zip/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/extsprintf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", - "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "optional": true - }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -8888,8 +7535,6 @@ }, "node_modules/fast-glob/node_modules/glob-parent": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { @@ -8901,22 +7546,31 @@ }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fastq": { "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "license": "ISC", "dependencies": { @@ -8925,8 +7579,6 @@ }, "node_modules/fault": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", - "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", "license": "MIT", "dependencies": { "format": "^0.2.0" @@ -8938,8 +7590,6 @@ }, "node_modules/fd-slicer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "license": "MIT", "dependencies": { @@ -8948,8 +7598,6 @@ }, "node_modules/fetch-blob": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", "funding": [ { "type": "github", @@ -8971,8 +7619,6 @@ }, "node_modules/file-entry-cache": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -8984,14 +7630,10 @@ }, "node_modules/file-uri-to-path": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, "node_modules/filelist": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9000,8 +7642,6 @@ }, "node_modules/filelist/node_modules/brace-expansion": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9010,8 +7650,6 @@ }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "license": "ISC", "dependencies": { @@ -9023,8 +7661,6 @@ }, "node_modules/fill-range": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { @@ -9036,8 +7672,6 @@ }, "node_modules/finalhandler": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -9053,8 +7687,6 @@ }, "node_modules/finalhandler/node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -9070,14 +7702,10 @@ }, "node_modules/finalhandler/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==", "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { @@ -9093,8 +7721,6 @@ }, "node_modules/flat-cache": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { @@ -9107,15 +7733,11 @@ }, "node_modules/flatted": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", "funding": [ { "type": "individual", @@ -9134,8 +7756,6 @@ }, "node_modules/foreground-child": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { @@ -9151,8 +7771,6 @@ }, "node_modules/foreground-child/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": { @@ -9164,8 +7782,6 @@ }, "node_modules/form-data": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -9180,8 +7796,6 @@ }, "node_modules/form-data/node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -9189,8 +7803,6 @@ }, "node_modules/form-data/node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -9201,16 +7813,12 @@ }, "node_modules/format": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", - "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", "engines": { "node": ">=0.4.x" } }, "node_modules/formdata-polyfill": { "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" @@ -9221,8 +7829,6 @@ }, "node_modules/forwarded": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -9230,8 +7836,6 @@ }, "node_modules/fresh": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -9239,14 +7843,10 @@ }, "node_modules/fs-constants": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, "node_modules/fs-extra": { "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", "dependencies": { @@ -9260,8 +7860,6 @@ }, "node_modules/fs-minipass": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "license": "ISC", "dependencies": { @@ -9273,29 +7871,11 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, "license": "ISC" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9303,17 +7883,24 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -9336,8 +7923,6 @@ }, "node_modules/get-nonce": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", - "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", "license": "MIT", "engines": { "node": ">=6" @@ -9345,8 +7930,6 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -9358,8 +7941,6 @@ }, "node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "license": "MIT", "dependencies": { @@ -9372,17 +7953,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/git-raw-commits": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^8.0.0", + "meow": "^12.0.1", + "split2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.mjs" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/github-from-package": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, "node_modules/glob": { "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -9402,8 +7994,6 @@ }, "node_modules/glob-parent": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { @@ -9415,8 +8005,6 @@ }, "node_modules/glob/node_modules/minimatch": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { @@ -9428,8 +8016,6 @@ }, "node_modules/global-agent": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", "dev": true, "license": "BSD-3-Clause", "optional": true, @@ -9447,8 +8033,6 @@ }, "node_modules/global-agent/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "optional": true, @@ -9459,10 +8043,30 @@ "node": ">=10" } }, + "node_modules/global-directory": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-directory/node_modules/ini": { + "version": "4.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/globals": { "version": "16.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", - "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", "dev": true, "license": "MIT", "engines": { @@ -9474,8 +8078,6 @@ }, "node_modules/globalthis": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", "optional": true, @@ -9492,8 +8094,6 @@ }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9504,8 +8104,6 @@ }, "node_modules/got": { "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", "dev": true, "license": "MIT", "dependencies": { @@ -9530,21 +8128,15 @@ }, "node_modules/graceful-fs": { "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, "license": "MIT" }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", "engines": { "node": ">=8" @@ -9552,8 +8144,6 @@ }, "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "optional": true, @@ -9566,8 +8156,6 @@ }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9578,8 +8166,6 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -9593,8 +8179,6 @@ }, "node_modules/hasown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9605,8 +8189,6 @@ }, "node_modules/hast-util-parse-selector": { "version": "2.2.5", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", - "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -9615,8 +8197,6 @@ }, "node_modules/hast-util-to-jsx-runtime": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -9642,8 +8222,6 @@ }, "node_modules/hast-util-whitespace": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" @@ -9655,8 +8233,6 @@ }, "node_modules/hastscript": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", - "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", "license": "MIT", "dependencies": { "@types/hast": "^2.0.0", @@ -9672,8 +8248,6 @@ }, "node_modules/hastscript/node_modules/@types/hast": { "version": "2.3.10", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.10.tgz", - "integrity": "sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==", "license": "MIT", "dependencies": { "@types/unist": "^2" @@ -9681,14 +8255,10 @@ }, "node_modules/hastscript/node_modules/@types/unist": { "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, "node_modules/hastscript/node_modules/comma-separated-tokens": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", - "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", "license": "MIT", "funding": { "type": "github", @@ -9697,8 +8267,6 @@ }, "node_modules/hastscript/node_modules/property-information": { "version": "5.6.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", - "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", "license": "MIT", "dependencies": { "xtend": "^4.0.0" @@ -9710,8 +8278,6 @@ }, "node_modules/hastscript/node_modules/space-separated-tokens": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", - "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", "license": "MIT", "funding": { "type": "github", @@ -9720,8 +8286,6 @@ }, "node_modules/highlight.js": { "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", "license": "BSD-3-Clause", "engines": { "node": "*" @@ -9729,14 +8293,10 @@ }, "node_modules/highlightjs-vue": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz", - "integrity": "sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==", "license": "CC0-1.0" }, "node_modules/hls-video-element": { "version": "1.5.8", - "resolved": "https://registry.npmjs.org/hls-video-element/-/hls-video-element-1.5.8.tgz", - "integrity": "sha512-DdeX5NzhM2Bj+ls5aaRrzSSnriK+r6lCrDa0YyfviNO4zb10JyAnJHZM214lXBWQghCm+fKmlWW1qpzdNoSAvQ==", "license": "MIT", "dependencies": { "custom-media-element": "^1.4.5", @@ -9746,14 +8306,10 @@ }, "node_modules/hls.js": { "version": "1.6.13", - "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.13.tgz", - "integrity": "sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA==", "license": "Apache-2.0" }, "node_modules/hosted-git-info": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, "license": "ISC", "dependencies": { @@ -9765,8 +8321,6 @@ }, "node_modules/html-entities": { "version": "2.6.0", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", - "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "funding": [ { "type": "github", @@ -9781,8 +8335,6 @@ }, "node_modules/html-parse-stringify": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", - "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", "license": "MIT", "dependencies": { "void-elements": "3.1.0" @@ -9790,8 +8342,6 @@ }, "node_modules/html-url-attributes": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz", - "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==", "license": "MIT", "funding": { "type": "opencollective", @@ -9800,15 +8350,11 @@ }, "node_modules/http-cache-semantics": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/http-errors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", "dependencies": { "depd": "2.0.0", @@ -9823,8 +8369,6 @@ }, "node_modules/http-errors/node_modules/statuses": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -9832,8 +8376,6 @@ }, "node_modules/http-proxy-agent": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { @@ -9846,8 +8388,6 @@ }, "node_modules/http-proxy-agent/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": { @@ -9864,15 +8404,11 @@ }, "node_modules/http-proxy-agent/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/http2-wrapper": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", "dev": true, "license": "MIT", "dependencies": { @@ -9885,8 +8421,6 @@ }, "node_modules/https-proxy-agent": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", "dev": true, "license": "MIT", "dependencies": { @@ -9899,8 +8433,6 @@ }, "node_modules/https-proxy-agent/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": { @@ -9917,25 +8449,33 @@ }, "node_modules/https-proxy-agent/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/humanize-ms": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "dev": true, "license": "MIT", "dependencies": { "ms": "^2.0.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, "node_modules/i18next": { "version": "25.5.3", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.5.3.tgz", - "integrity": "sha512-joFqorDeQ6YpIXni944upwnuHBf5IoPMuqAchGVeQLdWC2JOjxgM9V8UGLhNIIH/Q8QleRxIi0BSRQehSrDLcg==", "funding": [ { "type": "individual", @@ -9951,6 +8491,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.27.6" }, @@ -9965,35 +8506,13 @@ }, "node_modules/i18next-browser-languagedetector": { "version": "8.2.0", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.0.tgz", - "integrity": "sha512-P+3zEKLnOF0qmiesW383vsLdtQVyKtCNA9cjSoKCppTKPQVfKd2W8hbVo5ZhNJKDqeM7BOcvNoKJOjpHh4Js9g==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" } }, - "node_modules/iconv-corefoundation": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", - "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "cli-truncate": "^2.1.0", - "node-addon-api": "^1.6.3" - }, - "engines": { - "node": "^8.11.2 || >=10" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" @@ -10004,8 +8523,6 @@ }, "node_modules/ieee754": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "funding": [ { "type": "github", @@ -10024,8 +8541,6 @@ }, "node_modules/ignore": { "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -10034,14 +8549,20 @@ }, "node_modules/immediate": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", "license": "MIT" }, + "node_modules/immer": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.3.tgz", + "integrity": "sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10055,10 +8576,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imsc": { "version": "1.1.5", - "resolved": "https://registry.npmjs.org/imsc/-/imsc-1.1.5.tgz", - "integrity": "sha512-V8je+CGkcvGhgl2C1GlhqFFiUOIEdwXbXLiu1Fcubvvbo+g9inauqT3l0pNYXGoLPBj3jxtZz9t+wCopMkwadQ==", "license": "BSD-2-Clause", "dependencies": { "sax": "1.2.1" @@ -10066,14 +8594,10 @@ }, "node_modules/imsc/node_modules/sax": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", - "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==", "license": "ISC" }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { @@ -10082,8 +8606,6 @@ }, "node_modules/indent-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", "engines": { @@ -10092,16 +8614,11 @@ }, "node_modules/infer-owner": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true, "license": "ISC" }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", "dependencies": { @@ -10111,26 +8628,27 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, "node_modules/inline-style-parser": { "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", "license": "MIT" }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/ip-address": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", "dev": true, "license": "MIT", "engines": { @@ -10139,8 +8657,6 @@ }, "node_modules/ipaddr.js": { "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", "engines": { "node": ">= 0.10" @@ -10148,8 +8664,6 @@ }, "node_modules/is-alphabetical": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", "license": "MIT", "funding": { "type": "github", @@ -10158,8 +8672,6 @@ }, "node_modules/is-alphanumerical": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", "license": "MIT", "dependencies": { "is-alphabetical": "^2.0.0", @@ -10170,10 +8682,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, "node_modules/is-ci": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10185,8 +8700,6 @@ }, "node_modules/is-decimal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", "license": "MIT", "funding": { "type": "github", @@ -10195,8 +8708,6 @@ }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { @@ -10205,8 +8716,6 @@ }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", "engines": { "node": ">=8" @@ -10214,8 +8723,6 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { @@ -10227,8 +8734,6 @@ }, "node_modules/is-hexadecimal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", "license": "MIT", "funding": { "type": "github", @@ -10237,8 +8742,6 @@ }, "node_modules/is-interactive": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, "license": "MIT", "engines": { @@ -10247,25 +8750,27 @@ }, "node_modules/is-lambda": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", "dev": true, "license": "MIT" }, "node_modules/is-number": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "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==", "license": "MIT", "engines": { "node": ">=12" @@ -10276,14 +8781,21 @@ }, "node_modules/is-promise": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-text-path": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-unicode-supported": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", "engines": { @@ -10295,14 +8807,10 @@ }, "node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, "node_modules/isbinaryfile": { "version": "5.0.6", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", - "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", "dev": true, "license": "MIT", "engines": { @@ -10314,15 +8822,11 @@ }, "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/jackspeak": { "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -10337,8 +8841,6 @@ }, "node_modules/jake": { "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -10355,8 +8857,6 @@ }, "node_modules/jiti": { "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -10364,8 +8864,6 @@ }, "node_modules/joi": { "version": "18.0.1", - "resolved": "https://registry.npmjs.org/joi/-/joi-18.0.1.tgz", - "integrity": "sha512-IiQpRyypSnLisQf3PwuN2eIHAsAIGZIrLZkd4zdvIar2bDyhM91ubRjy8a3eYablXsh9BeI/c7dmPYHca5qtoA==", "license": "BSD-3-Clause", "dependencies": { "@hapi/address": "^5.1.1", @@ -10382,8 +8880,6 @@ }, "node_modules/jose": { "version": "5.10.0", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz", - "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -10391,20 +8887,14 @@ }, "node_modules/js-base64": { "version": "3.7.8", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.8.tgz", - "integrity": "sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==", "license": "BSD-3-Clause" }, "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==", "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", "dependencies": { @@ -10416,37 +8906,32 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/json-stringify-safe": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, "license": "ISC", "optional": true }, "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": { @@ -10458,18 +8943,37 @@ }, "node_modules/jsonfile": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "license": "MIT", "dependencies": { "jws": "^3.2.2", @@ -10490,14 +8994,10 @@ }, "node_modules/jsonwebtoken/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==", "license": "MIT" }, "node_modules/jsonwebtoken/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -10508,8 +9008,6 @@ }, "node_modules/jszip": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", "license": "(MIT OR GPL-3.0-or-later)", "dependencies": { "lie": "~3.3.0", @@ -10520,8 +9018,6 @@ }, "node_modules/jwa": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", - "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", "license": "MIT", "dependencies": { "buffer-equal-constant-time": "^1.0.1", @@ -10531,8 +9027,6 @@ }, "node_modules/jws": { "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", "license": "MIT", "dependencies": { "jwa": "^1.4.1", @@ -10541,8 +9035,6 @@ }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -10551,15 +9043,11 @@ }, "node_modules/lazy-val": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", - "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", "dev": true, "license": "MIT" }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -10572,8 +9060,6 @@ }, "node_modules/lie": { "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "license": "MIT", "dependencies": { "immediate": "~3.0.5" @@ -10789,8 +9275,6 @@ }, "node_modules/lightningcss-win32-x64-msvc": { "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", "cpu": [ "x64" ], @@ -10807,10 +9291,192 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "16.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^14.0.1", + "listr2": "^9.0.4", + "micromatch": "^4.0.8", + "nano-spawn": "^1.0.3", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.8.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "14.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/listr2": { + "version": "9.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^5.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^7.1.0", + "string-width": "^8.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/emoji-regex": { + "version": "10.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/string-width": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/strip-ansi": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/listr2/node_modules/wrap-ansi/node_modules/string-width": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/localforage": { "version": "1.10.0", - "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", - "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", "license": "Apache-2.0", "dependencies": { "lie": "3.1.1" @@ -10818,8 +9484,6 @@ }, "node_modules/localforage/node_modules/lie": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", "license": "MIT", "dependencies": { "immediate": "~3.0.5" @@ -10827,8 +9491,6 @@ }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { @@ -10843,63 +9505,78 @@ }, "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "dev": true, "license": "MIT" }, "node_modules/lodash.includes": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", "license": "MIT" }, "node_modules/lodash.isboolean": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", "license": "MIT" }, "node_modules/lodash.isinteger": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", "license": "MIT" }, "node_modules/lodash.isnumber": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "license": "MIT" }, "node_modules/lodash.isstring": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "dev": true, "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", "dev": true, "license": "MIT" }, "node_modules/lodash.once": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "dev": true, "license": "MIT" }, "node_modules/log-symbols": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { @@ -10913,10 +9590,182 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/cli-cursor": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/emoji-regex": { + "version": "10.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/onetime": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/restore-cursor": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/string-width": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/longest-streak": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", "license": "MIT", "funding": { "type": "github", @@ -10925,8 +9774,6 @@ }, "node_modules/loose-envify": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -10937,8 +9784,6 @@ }, "node_modules/lowercase-keys": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "dev": true, "license": "MIT", "engines": { @@ -10947,8 +9792,6 @@ }, "node_modules/lowlight": { "version": "1.20.0", - "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", - "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", "license": "MIT", "dependencies": { "fault": "^1.0.0", @@ -10961,8 +9804,6 @@ }, "node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "license": "ISC", "dependencies": { @@ -10974,8 +9815,6 @@ }, "node_modules/lucide-react": { "version": "0.525.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.525.0.tgz", - "integrity": "sha512-Tm1txJ2OkymCGkvwoHt33Y2JpN5xucVq1slHcgE6Lk0WjDfjgKWor5CdVER8U6DvcfMwh4M8XxmpTiyzfmfDYQ==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" @@ -10992,8 +9831,6 @@ }, "node_modules/make-cancellable-promise": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/make-cancellable-promise/-/make-cancellable-promise-2.0.0.tgz", - "integrity": "sha512-3SEQqTpV9oqVsIWqAcmDuaNeo7yBO3tqPtqGRcKkEo0lrzD3wqbKG9mkxO65KoOgXqj+zH2phJ2LiAsdzlogSw==", "license": "MIT", "funding": { "url": "https://github.com/wojtekmaj/make-cancellable-promise?sponsor=1" @@ -11001,8 +9838,6 @@ }, "node_modules/make-event-props": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-2.0.0.tgz", - "integrity": "sha512-G/hncXrl4Qt7mauJEXSg3AcdYzmpkIITTNl5I+rH9sog5Yw0kK6vseJjCaPfOXqOqQuPUP89Rkhfz5kPS8ijtw==", "license": "MIT", "funding": { "url": "https://github.com/wojtekmaj/make-event-props?sponsor=1" @@ -11010,8 +9845,6 @@ }, "node_modules/make-fetch-happen": { "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "license": "ISC", "dependencies": { @@ -11038,8 +9871,6 @@ }, "node_modules/make-fetch-happen/node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -11051,8 +9882,6 @@ }, "node_modules/make-fetch-happen/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": { @@ -11069,8 +9898,6 @@ }, "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, "license": "MIT", "dependencies": { @@ -11084,8 +9911,6 @@ }, "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dev": true, "license": "MIT", "dependencies": { @@ -11098,8 +9923,6 @@ }, "node_modules/make-fetch-happen/node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "license": "ISC", "engines": { @@ -11108,15 +9931,11 @@ }, "node_modules/make-fetch-happen/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/make-fetch-happen/node_modules/negotiator": { "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", "dev": true, "license": "MIT", "engines": { @@ -11125,8 +9944,6 @@ }, "node_modules/markdown-table": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", "license": "MIT", "funding": { "type": "github", @@ -11135,8 +9952,6 @@ }, "node_modules/matcher": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", "dev": true, "license": "MIT", "optional": true, @@ -11149,8 +9964,6 @@ }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -11158,8 +9971,6 @@ }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11174,8 +9985,6 @@ }, "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { "node": ">=12" @@ -11186,8 +9995,6 @@ }, "node_modules/mdast-util-from-markdown": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11210,8 +10017,6 @@ }, "node_modules/mdast-util-gfm": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", "license": "MIT", "dependencies": { "mdast-util-from-markdown": "^2.0.0", @@ -11229,8 +10034,6 @@ }, "node_modules/mdast-util-gfm-autolink-literal": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11246,8 +10049,6 @@ }, "node_modules/mdast-util-gfm-footnote": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11263,8 +10064,6 @@ }, "node_modules/mdast-util-gfm-strikethrough": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11278,8 +10077,6 @@ }, "node_modules/mdast-util-gfm-table": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11295,8 +10092,6 @@ }, "node_modules/mdast-util-gfm-task-list-item": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11311,8 +10106,6 @@ }, "node_modules/mdast-util-mdx-expression": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -11329,8 +10122,6 @@ }, "node_modules/mdast-util-mdx-jsx": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -11353,8 +10144,6 @@ }, "node_modules/mdast-util-mdxjs-esm": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", @@ -11371,8 +10160,6 @@ }, "node_modules/mdast-util-phrasing": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11385,8 +10172,6 @@ }, "node_modules/mdast-util-to-hast": { "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -11406,8 +10191,6 @@ }, "node_modules/mdast-util-to-markdown": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -11427,8 +10210,6 @@ }, "node_modules/mdast-util-to-string": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0" @@ -11440,8 +10221,6 @@ }, "node_modules/media-chrome": { "version": "4.14.0", - "resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.14.0.tgz", - "integrity": "sha512-IEdFb4blyF15vLvQzLIn6USJBv7Kf2ne+TfLQKBYI5Z0f9VEBVZz5MKy4Uhi0iA9lStl2S9ENIujJRuJIa5OiA==", "license": "MIT", "dependencies": { "ce-la-react": "^0.3.0" @@ -11449,23 +10228,28 @@ }, "node_modules/media-tracks": { "version": "0.3.3", - "resolved": "https://registry.npmjs.org/media-tracks/-/media-tracks-0.3.3.tgz", - "integrity": "sha512-9P2FuUHnZZ3iji+2RQk7Zkh5AmZTnOG5fODACnjhCVveX1McY3jmCRHofIEI+yTBqplz7LXy48c7fQ3Uigp88w==", "license": "MIT" }, "node_modules/media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/meow": { + "version": "12.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-descriptors": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "license": "MIT", "engines": { "node": ">=18" @@ -11476,8 +10260,6 @@ }, "node_modules/merge-refs": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-2.0.0.tgz", - "integrity": "sha512-3+B21mYK2IqUWnd2EivABLT7ueDhb0b8/dGK8LoFQPrU61YITeCMn14F7y7qZafWNZhUEKb24cJdiT5Wxs3prg==", "license": "MIT", "funding": { "url": "https://github.com/wojtekmaj/merge-refs?sponsor=1" @@ -11493,8 +10275,6 @@ }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", "engines": { @@ -11503,8 +10283,6 @@ }, "node_modules/micromark": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", "funding": [ { "type": "GitHub Sponsors", @@ -11538,8 +10316,6 @@ }, "node_modules/micromark-core-commonmark": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", "funding": [ { "type": "GitHub Sponsors", @@ -11572,8 +10348,6 @@ }, "node_modules/micromark-extension-gfm": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", "license": "MIT", "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", @@ -11592,8 +10366,6 @@ }, "node_modules/micromark-extension-gfm-autolink-literal": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", @@ -11608,8 +10380,6 @@ }, "node_modules/micromark-extension-gfm-footnote": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -11628,8 +10398,6 @@ }, "node_modules/micromark-extension-gfm-strikethrough": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -11646,8 +10414,6 @@ }, "node_modules/micromark-extension-gfm-table": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -11663,8 +10429,6 @@ }, "node_modules/micromark-extension-gfm-tagfilter": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", "license": "MIT", "dependencies": { "micromark-util-types": "^2.0.0" @@ -11676,8 +10440,6 @@ }, "node_modules/micromark-extension-gfm-task-list-item": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -11693,8 +10455,6 @@ }, "node_modules/micromark-factory-destination": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", "funding": [ { "type": "GitHub Sponsors", @@ -11714,8 +10474,6 @@ }, "node_modules/micromark-factory-label": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", "funding": [ { "type": "GitHub Sponsors", @@ -11736,8 +10494,6 @@ }, "node_modules/micromark-factory-space": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", "funding": [ { "type": "GitHub Sponsors", @@ -11756,8 +10512,6 @@ }, "node_modules/micromark-factory-title": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", "funding": [ { "type": "GitHub Sponsors", @@ -11778,8 +10532,6 @@ }, "node_modules/micromark-factory-whitespace": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11800,8 +10552,6 @@ }, "node_modules/micromark-util-character": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11820,8 +10570,6 @@ }, "node_modules/micromark-util-chunked": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", "funding": [ { "type": "GitHub Sponsors", @@ -11839,8 +10587,6 @@ }, "node_modules/micromark-util-classify-character": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11860,8 +10606,6 @@ }, "node_modules/micromark-util-combine-extensions": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", "funding": [ { "type": "GitHub Sponsors", @@ -11880,8 +10624,6 @@ }, "node_modules/micromark-util-decode-numeric-character-reference": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", "funding": [ { "type": "GitHub Sponsors", @@ -11899,8 +10641,6 @@ }, "node_modules/micromark-util-decode-string": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", "funding": [ { "type": "GitHub Sponsors", @@ -11921,8 +10661,6 @@ }, "node_modules/micromark-util-encode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "funding": [ { "type": "GitHub Sponsors", @@ -11937,8 +10675,6 @@ }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", "funding": [ { "type": "GitHub Sponsors", @@ -11953,8 +10689,6 @@ }, "node_modules/micromark-util-normalize-identifier": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", "funding": [ { "type": "GitHub Sponsors", @@ -11972,8 +10706,6 @@ }, "node_modules/micromark-util-resolve-all": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", "funding": [ { "type": "GitHub Sponsors", @@ -11991,8 +10723,6 @@ }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", @@ -12012,8 +10742,6 @@ }, "node_modules/micromark-util-subtokenize": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", "funding": [ { "type": "GitHub Sponsors", @@ -12034,8 +10762,6 @@ }, "node_modules/micromark-util-symbol": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", @@ -12050,8 +10776,6 @@ }, "node_modules/micromark-util-types": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { "type": "GitHub Sponsors", @@ -12066,8 +10790,6 @@ }, "node_modules/micromark/node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -12083,14 +10805,10 @@ }, "node_modules/micromark/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==", "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -12103,8 +10821,6 @@ }, "node_modules/mime": { "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, "license": "MIT", "bin": { @@ -12116,8 +10832,6 @@ }, "node_modules/mime-db": { "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -12125,8 +10839,6 @@ }, "node_modules/mime-types": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", "license": "MIT", "dependencies": { "mime-db": "^1.54.0" @@ -12137,18 +10849,25 @@ }, "node_modules/mimic-fn": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mimic-response": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", "dev": true, "license": "MIT", "engines": { @@ -12157,8 +10876,6 @@ }, "node_modules/minimatch": { "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", "dev": true, "license": "ISC", "dependencies": { @@ -12173,8 +10890,6 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -12182,8 +10897,6 @@ }, "node_modules/minipass": { "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "license": "ISC", "dependencies": { @@ -12195,8 +10908,6 @@ }, "node_modules/minipass-collect": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "license": "ISC", "dependencies": { @@ -12208,8 +10919,6 @@ }, "node_modules/minipass-fetch": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", "dev": true, "license": "MIT", "dependencies": { @@ -12226,8 +10935,6 @@ }, "node_modules/minipass-flush": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "license": "ISC", "dependencies": { @@ -12239,8 +10946,6 @@ }, "node_modules/minipass-pipeline": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "license": "ISC", "dependencies": { @@ -12252,8 +10957,6 @@ }, "node_modules/minipass-sized": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "license": "ISC", "dependencies": { @@ -12265,8 +10968,6 @@ }, "node_modules/minizlib": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "license": "MIT", "dependencies": { @@ -12279,8 +10980,6 @@ }, "node_modules/mkdirp": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", "bin": { @@ -12292,14 +10991,10 @@ }, "node_modules/mkdirp-classic": { "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", "license": "MIT" }, "node_modules/monaco-editor": { "version": "0.53.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.53.0.tgz", - "integrity": "sha512-0WNThgC6CMWNXXBxTbaYYcunj08iB5rnx4/G56UOPeL9UVIUGGHA1GR0EWIh9Ebabj7NpCRawQ5b0hfN1jQmYQ==", "license": "MIT", "peer": true, "dependencies": { @@ -12308,14 +11003,10 @@ }, "node_modules/ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, "node_modules/multer": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", - "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", "license": "MIT", "dependencies": { "append-field": "^1.0.0", @@ -12332,8 +11023,6 @@ }, "node_modules/multer/node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "license": "MIT", "dependencies": { "minimist": "^1.2.6" @@ -12344,21 +11033,21 @@ }, "node_modules/mux-embed": { "version": "5.9.0", - "resolved": "https://registry.npmjs.org/mux-embed/-/mux-embed-5.9.0.tgz", - "integrity": "sha512-wmunL3uoPhma/tWy8PrDPZkvJpXvSFBwbD3KkC4PG8Ztjfb1X3hRJwGUAQyRz7z99b/ovLm2UTTitrkvStjH4w==", "license": "MIT" }, - "node_modules/nan": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz", - "integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==", + "node_modules/nano-spawn": { + "version": "1.0.3", + "dev": true, "license": "MIT", - "optional": true + "engines": { + "node": ">=20.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" + } }, "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==", "funding": [ { "type": "github", @@ -12375,27 +11064,19 @@ }, "node_modules/napi-build-utils": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", - "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", "license": "MIT" }, "node_modules/native-promise-only": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==", "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/negotiator": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -12403,8 +11084,6 @@ }, "node_modules/next-themes": { "version": "0.4.6", - "resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz", - "integrity": "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==", "license": "MIT", "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", @@ -12413,8 +11092,6 @@ }, "node_modules/node-abi": { "version": "3.77.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.77.0.tgz", - "integrity": "sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -12425,8 +11102,6 @@ }, "node_modules/node-abi/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -12435,18 +11110,8 @@ "node": ">=10" } }, - "node_modules/node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/node-api-version": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz", - "integrity": "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -12455,8 +11120,6 @@ }, "node_modules/node-api-version/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -12468,9 +11131,6 @@ }, "node_modules/node-domexception": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", "funding": [ { "type": "github", @@ -12488,8 +11148,6 @@ }, "node_modules/node-fetch": { "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", @@ -12506,8 +11164,6 @@ }, "node_modules/nopt": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, "license": "ISC", "dependencies": { @@ -12522,8 +11178,6 @@ }, "node_modules/normalize-url": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, "license": "MIT", "engines": { @@ -12535,8 +11189,6 @@ }, "node_modules/object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12544,8 +11196,6 @@ }, "node_modules/object-inspect": { "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -12556,8 +11206,6 @@ }, "node_modules/object-keys": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", "optional": true, @@ -12567,8 +11215,6 @@ }, "node_modules/on-finished": { "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "license": "MIT", "dependencies": { "ee-first": "1.1.1" @@ -12579,8 +11225,6 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", "dependencies": { "wrappy": "1" @@ -12588,8 +11232,6 @@ }, "node_modules/onetime": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", "dependencies": { @@ -12604,8 +11246,6 @@ }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -12622,8 +11262,6 @@ }, "node_modules/ora": { "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12646,8 +11284,6 @@ }, "node_modules/p-cancelable": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true, "license": "MIT", "engines": { @@ -12656,8 +11292,6 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12672,8 +11306,6 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -12688,8 +11320,6 @@ }, "node_modules/p-map": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12704,8 +11334,6 @@ }, "node_modules/p-try": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "license": "MIT", "engines": { "node": ">=6" @@ -12713,21 +11341,15 @@ }, "node_modules/package-json-from-dist": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/pako": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "license": "(MIT AND Zlib)" }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { @@ -12739,8 +11361,6 @@ }, "node_modules/parse-entities": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", @@ -12758,14 +11378,27 @@ }, "node_modules/parse-entities/node_modules/@types/unist": { "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, + "node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parseurl": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -12773,14 +11406,10 @@ }, "node_modules/path-browserify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", "license": "MIT" }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "license": "MIT", "engines": { "node": ">=8" @@ -12788,8 +11417,6 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", "engines": { @@ -12798,8 +11425,6 @@ }, "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": { @@ -12808,8 +11433,6 @@ }, "node_modules/path-scurry": { "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -12825,15 +11448,11 @@ }, "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, "license": "ISC" }, "node_modules/path-scurry/node_modules/minipass": { "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "license": "ISC", "engines": { @@ -12842,8 +11461,6 @@ }, "node_modules/path-to-regexp": { "version": "8.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", - "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "license": "MIT", "funding": { "type": "opencollective", @@ -12852,8 +11469,6 @@ }, "node_modules/pdfjs-dist": { "version": "5.3.93", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.3.93.tgz", - "integrity": "sha512-w3fQKVL1oGn8FRyx5JUG5tnbblggDqyx2XzA5brsJ5hSuS+I0NdnJANhmeWKLjotdbPQucLBug5t0MeWr0AAdg==", "license": "Apache-2.0", "engines": { "node": ">=20.16.0 || >=22.3.0" @@ -12864,8 +11479,6 @@ }, "node_modules/pe-library": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", - "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", "dev": true, "license": "MIT", "engines": { @@ -12879,21 +11492,15 @@ }, "node_modules/pend": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { @@ -12903,10 +11510,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/player.style": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/player.style/-/player.style-0.2.0.tgz", - "integrity": "sha512-Ngoaz49TClptMr8HDA2IFmjT3Iq6R27QEUH/C+On33L59RSF3dCLefBYB1Au2RDZQJ6oVFpc1sXaPVpp7fEzzA==", "license": "MIT", "workspaces": [ ".", @@ -12921,8 +11537,6 @@ }, "node_modules/player.style/node_modules/media-chrome": { "version": "4.13.1", - "resolved": "https://registry.npmjs.org/media-chrome/-/media-chrome-4.13.1.tgz", - "integrity": "sha512-jPPwYrFkM4ky27/xNYEeyRPOBC7qvru4Oydy7vQHMHplXLQJmjtcauhlLPvG0O5kkYFEaOBXv5zGYes/UxOoVw==", "license": "MIT", "dependencies": { "ce-la-react": "^0.3.0" @@ -12930,8 +11544,6 @@ }, "node_modules/plist": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12945,8 +11557,6 @@ }, "node_modules/pngjs": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", "license": "MIT", "engines": { "node": ">=10.13.0" @@ -12954,8 +11564,6 @@ }, "node_modules/postcss": { "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "funding": [ { "type": "opencollective", @@ -12982,8 +11590,6 @@ }, "node_modules/postcss/node_modules/nanoid": { "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -13000,12 +11606,9 @@ }, "node_modules/postject": { "version": "1.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", - "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "commander": "^9.4.0" }, @@ -13018,20 +11621,15 @@ }, "node_modules/postject/node_modules/commander": { "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", "dev": true, "license": "MIT", "optional": true, - "peer": true, "engines": { "node": "^12.20.0 || >=14" } }, "node_modules/prebuild-install": { "version": "7.1.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", - "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", "license": "MIT", "dependencies": { "detect-libc": "^2.0.0", @@ -13056,8 +11654,6 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { @@ -13066,8 +11662,6 @@ }, "node_modules/prettier": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -13082,8 +11676,6 @@ }, "node_modules/prismjs": { "version": "1.30.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", - "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", "license": "MIT", "engines": { "node": ">=6" @@ -13091,8 +11683,6 @@ }, "node_modules/proc-log": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", "dev": true, "license": "ISC", "engines": { @@ -13101,14 +11691,10 @@ }, "node_modules/process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, "license": "MIT", "engines": { @@ -13117,15 +11703,11 @@ }, "node_modules/promise-inflight": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, "license": "ISC" }, "node_modules/promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "dev": true, "license": "MIT", "dependencies": { @@ -13138,8 +11720,6 @@ }, "node_modules/prop-types": { "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -13149,8 +11729,6 @@ }, "node_modules/property-information": { "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", "funding": { "type": "github", @@ -13159,8 +11737,6 @@ }, "node_modules/proxy-addr": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "license": "MIT", "dependencies": { "forwarded": "0.2.0", @@ -13172,14 +11748,10 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, "node_modules/pump": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", - "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -13188,8 +11760,6 @@ }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { @@ -13198,8 +11768,6 @@ }, "node_modules/qrcode": { "version": "1.5.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", "license": "MIT", "dependencies": { "dijkstrajs": "^1.0.1", @@ -13215,8 +11783,6 @@ }, "node_modules/qrcode/node_modules/cliui": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -13226,8 +11792,6 @@ }, "node_modules/qrcode/node_modules/find-up": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -13239,8 +11803,6 @@ }, "node_modules/qrcode/node_modules/locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -13251,8 +11813,6 @@ }, "node_modules/qrcode/node_modules/p-limit": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -13266,8 +11826,6 @@ }, "node_modules/qrcode/node_modules/p-locate": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -13278,8 +11836,6 @@ }, "node_modules/qrcode/node_modules/wrap-ansi": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -13292,14 +11848,10 @@ }, "node_modules/qrcode/node_modules/y18n": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "license": "ISC" }, "node_modules/qrcode/node_modules/yargs": { "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "license": "MIT", "dependencies": { "cliui": "^6.0.0", @@ -13320,8 +11872,6 @@ }, "node_modules/qrcode/node_modules/yargs-parser": { "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "license": "ISC", "dependencies": { "camelcase": "^5.0.0", @@ -13333,8 +11883,6 @@ }, "node_modules/qs": { "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.6" @@ -13348,8 +11896,6 @@ }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -13369,8 +11915,6 @@ }, "node_modules/quick-lru": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, "license": "MIT", "engines": { @@ -13382,8 +11926,6 @@ }, "node_modules/range-parser": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -13391,8 +11933,6 @@ }, "node_modules/raw-body": { "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "license": "MIT", "dependencies": { "bytes": "3.1.2", @@ -13406,8 +11946,6 @@ }, "node_modules/rc": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", "dependencies": { "deep-extend": "^0.6.0", @@ -13421,8 +11959,6 @@ }, "node_modules/rc/node_modules/strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13430,18 +11966,16 @@ }, "node_modules/react": { "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", - "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { "version": "19.1.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", - "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.26.0" }, @@ -13451,8 +11985,6 @@ }, "node_modules/react-h5-audio-player": { "version": "3.10.1", - "resolved": "https://registry.npmjs.org/react-h5-audio-player/-/react-h5-audio-player-3.10.1.tgz", - "integrity": "sha512-r6fSj9WXR6af1kxH5qQ/tawwDK4KrMfayiVCUettLYGX/KZ3BH8OGuaZP4O5KD0AxwsKAXtBv4kVQCWFzaIrUA==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.2", @@ -13465,9 +11997,8 @@ }, "node_modules/react-hook-form": { "version": "7.63.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.63.0.tgz", - "integrity": "sha512-ZwueDMvUeucovM2VjkCf7zIHcs1aAlDimZu2Hvel5C5907gUzMpm4xCrQXtRzCvsBqFjonB4m3x4LzCFI1ZKWA==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -13481,8 +12012,6 @@ }, "node_modules/react-i18next": { "version": "15.7.4", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.7.4.tgz", - "integrity": "sha512-nyU8iKNrI5uDJch0z9+Y5XEr34b0wkyYj3Rp+tfbahxtlswxSCjcUL9H0nqXo9IR3/t5Y5PKIA3fx3MfUyR9Xw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.27.6", @@ -13507,8 +12036,6 @@ }, "node_modules/react-icons": { "version": "5.5.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", - "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", "license": "MIT", "peerDependencies": { "react": "*" @@ -13516,14 +12043,11 @@ }, "node_modules/react-is": { "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/react-markdown": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz", - "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -13549,8 +12073,6 @@ }, "node_modules/react-pdf": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-10.1.0.tgz", - "integrity": "sha512-iUI1YqWgwwZcsXjrehTp3Yi8nT/bvTaWULaRMMyJWvoqqSlopk4LQQ9GDqUnDtX3gzT2glrqrLbjIPl56a+Q3w==", "license": "MIT", "dependencies": { "clsx": "^2.0.0", @@ -13578,8 +12100,6 @@ }, "node_modules/react-photo-view": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/react-photo-view/-/react-photo-view-1.2.7.tgz", - "integrity": "sha512-MfOWVPxuibncRLaycZUNxqYU8D9IA+rbGDDaq6GM8RIoGJal592hEJoRAyRSI7ZxyyJNJTLMUWWL3UIXHJJOpw==", "license": "Apache-2.0", "peerDependencies": { "react": ">=16.8.0", @@ -13588,8 +12108,6 @@ }, "node_modules/react-player": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/react-player/-/react-player-3.3.3.tgz", - "integrity": "sha512-6U2ziVohA3WLdKI/WEQ7v27CIive0TCNIro55lJZka06fjB2kC4lJqBrvddG0yBvTDcn1owiUf2hRNaIzHAjIg==", "license": "MIT", "dependencies": { "@mux/mux-player-react": "^3.6.0", @@ -13609,10 +12127,32 @@ "react-dom": "^17.0.2 || ^18 || ^19" } }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, "node_modules/react-remove-scroll": { "version": "2.7.1", - "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz", - "integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==", "license": "MIT", "dependencies": { "react-remove-scroll-bar": "^2.3.7", @@ -13636,8 +12176,6 @@ }, "node_modules/react-remove-scroll-bar": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", - "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", "license": "MIT", "dependencies": { "react-style-singleton": "^2.2.2", @@ -13658,8 +12196,6 @@ }, "node_modules/react-resizable-panels": { "version": "3.0.6", - "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.6.tgz", - "integrity": "sha512-b3qKHQ3MLqOgSS+FRYKapNkJZf5EQzuf6+RLiq1/IlTHw99YrZ2NJZLk4hQIzTnnIkRg2LUqyVinu6YWWpUYew==", "license": "MIT", "peerDependencies": { "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -13668,8 +12204,6 @@ }, "node_modules/react-simple-keyboard": { "version": "3.8.125", - "resolved": "https://registry.npmjs.org/react-simple-keyboard/-/react-simple-keyboard-3.8.125.tgz", - "integrity": "sha512-8+PbmGA2auM7V57hapHsKV7IJcJVl0QNNW09RJQ7xCiohHuZNKvqrxGvisxhhr7X8C8TKulxbqdxjZbFelwO7w==", "license": "MIT", "peerDependencies": { "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", @@ -13678,8 +12212,6 @@ }, "node_modules/react-style-singleton": { "version": "2.2.3", - "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", - "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", "license": "MIT", "dependencies": { "get-nonce": "^1.0.0", @@ -13700,8 +12232,6 @@ }, "node_modules/react-syntax-highlighter": { "version": "15.6.6", - "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.6.6.tgz", - "integrity": "sha512-DgXrc+AZF47+HvAPEmn7Ua/1p10jNoVZVI/LoPiYdtY+OM+/nG5yefLHKJwdKqY1adMuHFbeyBaG9j64ML7vTw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.3.1", @@ -13717,8 +12247,6 @@ }, "node_modules/react-xtermjs": { "version": "1.0.10", - "resolved": "https://registry.npmjs.org/react-xtermjs/-/react-xtermjs-1.0.10.tgz", - "integrity": "sha512-+xpKEKbmsypWzRKE0FR1LNIGcI8gx+R6VMHe8IQW7iTbgeqp3Qg7SbiVNOzR+Ovb1QK4DPA3KqsIQV+XP0iRUA==", "license": "ISC", "peerDependencies": { "@xterm/xterm": "^5.5.0" @@ -13726,8 +12254,6 @@ }, "node_modules/read-binary-file-arch": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", - "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", "dev": true, "license": "MIT", "dependencies": { @@ -13739,8 +12265,6 @@ }, "node_modules/read-binary-file-arch/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": { @@ -13757,15 +12281,11 @@ }, "node_modules/read-binary-file-arch/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/readable-stream": { "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", "dependencies": { "core-util-is": "~1.0.0", @@ -13779,14 +12299,53 @@ }, "node_modules/readable-stream/node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/recharts": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.2.1.tgz", + "integrity": "sha512-0JKwHRiFZdmLq/6nmilxEZl3pqb4T+aKkOkOi/ZISRZwfBhVMgInxzlYU9D4KnCH3KINScLy68m/OvMXoYGZUw==", + "license": "MIT", + "dependencies": { + "@reduxjs/toolkit": "1.x.x || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT", + "peer": true + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, "node_modules/refractor": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.6.0.tgz", - "integrity": "sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA==", "license": "MIT", "dependencies": { "hastscript": "^6.0.0", @@ -13800,8 +12359,6 @@ }, "node_modules/refractor/node_modules/character-entities": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", - "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", "license": "MIT", "funding": { "type": "github", @@ -13810,8 +12367,6 @@ }, "node_modules/refractor/node_modules/character-entities-legacy": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", - "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", "license": "MIT", "funding": { "type": "github", @@ -13820,8 +12375,6 @@ }, "node_modules/refractor/node_modules/character-reference-invalid": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", - "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", "license": "MIT", "funding": { "type": "github", @@ -13830,8 +12383,6 @@ }, "node_modules/refractor/node_modules/is-alphabetical": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", - "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", "license": "MIT", "funding": { "type": "github", @@ -13840,8 +12391,6 @@ }, "node_modules/refractor/node_modules/is-alphanumerical": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", - "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "license": "MIT", "dependencies": { "is-alphabetical": "^1.0.0", @@ -13854,8 +12403,6 @@ }, "node_modules/refractor/node_modules/is-decimal": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", - "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", "license": "MIT", "funding": { "type": "github", @@ -13864,8 +12411,6 @@ }, "node_modules/refractor/node_modules/is-hexadecimal": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", - "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", "license": "MIT", "funding": { "type": "github", @@ -13874,8 +12419,6 @@ }, "node_modules/refractor/node_modules/parse-entities": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", - "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", "license": "MIT", "dependencies": { "character-entities": "^1.0.0", @@ -13892,8 +12435,6 @@ }, "node_modules/refractor/node_modules/prismjs": { "version": "1.27.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", - "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==", "license": "MIT", "engines": { "node": ">=6" @@ -13901,8 +12442,6 @@ }, "node_modules/remark-gfm": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -13919,8 +12458,6 @@ }, "node_modules/remark-parse": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -13935,8 +12472,6 @@ }, "node_modules/remark-rehype": { "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -13952,8 +12487,6 @@ }, "node_modules/remark-stringify": { "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -13967,8 +12500,14 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -13976,14 +12515,10 @@ }, "node_modules/require-main-filename": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "license": "ISC" }, "node_modules/resedit": { "version": "1.7.2", - "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", - "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", "dev": true, "license": "MIT", "dependencies": { @@ -13998,17 +12533,19 @@ "url": "https://github.com/sponsors/jet2jet" } }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, "node_modules/resolve-alpn": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "dev": true, "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { @@ -14017,8 +12554,6 @@ }, "node_modules/responselike": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", "dev": true, "license": "MIT", "dependencies": { @@ -14030,8 +12565,6 @@ }, "node_modules/restore-cursor": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "license": "MIT", "dependencies": { @@ -14044,8 +12577,6 @@ }, "node_modules/retry": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", "dev": true, "license": "MIT", "engines": { @@ -14054,8 +12585,6 @@ }, "node_modules/reusify": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -14063,11 +12592,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -14082,8 +12613,6 @@ }, "node_modules/roarr": { "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", "dev": true, "license": "BSD-3-Clause", "optional": true, @@ -14101,8 +12630,6 @@ }, "node_modules/rollup": { "version": "4.52.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.3.tgz", - "integrity": "sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -14142,8 +12669,6 @@ }, "node_modules/router": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", - "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "license": "MIT", "dependencies": { "debug": "^4.4.0", @@ -14158,8 +12683,6 @@ }, "node_modules/router/node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -14175,14 +12698,10 @@ }, "node_modules/router/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==", "license": "MIT" }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -14205,8 +12724,6 @@ }, "node_modules/rxjs": { "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -14214,8 +12731,6 @@ }, "node_modules/safe-buffer": { "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ { "type": "github", @@ -14234,14 +12749,10 @@ }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, "node_modules/sanitize-filename": { "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "dev": true, "license": "WTFPL OR ISC", "dependencies": { @@ -14250,21 +12761,15 @@ }, "node_modules/sax": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "dev": true, "license": "ISC" }, "node_modules/scheduler": { "version": "0.26.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", "license": "MIT" }, "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": { @@ -14273,16 +12778,12 @@ }, "node_modules/semver-compare": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, "license": "MIT", "optional": true }, "node_modules/send": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", "license": "MIT", "dependencies": { "debug": "^4.3.5", @@ -14303,8 +12804,6 @@ }, "node_modules/send/node_modules/debug": { "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -14320,14 +12819,10 @@ }, "node_modules/send/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==", "license": "MIT" }, "node_modules/serialize-error": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", "dev": true, "license": "MIT", "optional": true, @@ -14343,8 +12838,6 @@ }, "node_modules/serve-static": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", @@ -14358,26 +12851,18 @@ }, "node_modules/set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "license": "ISC" }, "node_modules/setimmediate": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "license": "ISC" }, "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": { @@ -14389,8 +12874,6 @@ }, "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": { @@ -14399,8 +12882,6 @@ }, "node_modules/shell-quote": { "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", "engines": { @@ -14412,8 +12893,6 @@ }, "node_modules/side-channel": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -14431,8 +12910,6 @@ }, "node_modules/side-channel-list": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -14447,8 +12924,6 @@ }, "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -14465,8 +12940,6 @@ }, "node_modules/side-channel-weakmap": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", "dependencies": { "call-bound": "^1.0.2", @@ -14484,15 +12957,11 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, "license": "ISC" }, "node_modules/simple-concat": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", "funding": [ { "type": "github", @@ -14511,8 +12980,6 @@ }, "node_modules/simple-get": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", - "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "funding": [ { "type": "github", @@ -14536,8 +13003,6 @@ }, "node_modules/simple-update-notifier": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", - "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, "license": "MIT", "dependencies": { @@ -14549,8 +13014,6 @@ }, "node_modules/simple-update-notifier/node_modules/semver": { "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, "license": "ISC", "bin": { @@ -14560,26 +13023,8 @@ "node": ">=10" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/smart-buffer": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "license": "MIT", "engines": { @@ -14589,8 +13034,6 @@ }, "node_modules/socks": { "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "dev": true, "license": "MIT", "dependencies": { @@ -14604,8 +13047,6 @@ }, "node_modules/socks-proxy-agent": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "license": "MIT", "dependencies": { @@ -14619,8 +13060,6 @@ }, "node_modules/socks-proxy-agent/node_modules/agent-base": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14632,8 +13071,6 @@ }, "node_modules/socks-proxy-agent/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": { @@ -14650,15 +13087,11 @@ }, "node_modules/socks-proxy-agent/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/sonner": { "version": "2.0.7", - "resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz", - "integrity": "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==", "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", @@ -14667,8 +13100,6 @@ }, "node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -14677,8 +13108,6 @@ }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -14686,8 +13115,6 @@ }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { @@ -14697,8 +13124,6 @@ }, "node_modules/space-separated-tokens": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", "funding": { "type": "github", @@ -14707,8 +13132,6 @@ }, "node_modules/speakeasy": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/speakeasy/-/speakeasy-2.0.0.tgz", - "integrity": "sha512-lW2A2s5LKi8rwu77ewisuUOtlCydF/hmQSOJjpTqTj1gZLkNgTaYnyvfxy2WBr4T/h+9c4g8HIITfj83OkFQFw==", "license": "MIT", "dependencies": { "base32.js": "0.0.1" @@ -14717,24 +13140,26 @@ "node": ">= 0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/spotify-audio-element": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/spotify-audio-element/-/spotify-audio-element-1.0.3.tgz", - "integrity": "sha512-I1/qD8cg/UnTlCIMiKSdZUJTyYfYhaqFK7LIVElc48eOqUUbVCaw1bqL8I6mJzdMJTh3eoNyF/ewvB7NoS/g9A==", "license": "MIT" }, "node_modules/sprintf-js": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true, "license": "BSD-3-Clause", "optional": true }, "node_modules/ssh2": { "version": "1.17.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.17.0.tgz", - "integrity": "sha512-wPldCk3asibAjQ/kziWQQt1Wh3PgDFpC0XpwclzKcdT1vql6KeYxf5LIt4nlFkUeR8WuphYMKqUA56X4rjbfgQ==", "hasInstallScript": true, "dependencies": { "asn1": "^0.2.6", @@ -14750,8 +13175,6 @@ }, "node_modules/ssri": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, "license": "ISC", "dependencies": { @@ -14763,8 +13186,6 @@ }, "node_modules/stat-mode": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", - "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true, "license": "MIT", "engines": { @@ -14773,14 +13194,10 @@ }, "node_modules/state-local": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", - "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", "license": "MIT" }, "node_modules/statuses": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -14788,16 +13205,12 @@ }, "node_modules/streamsearch": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "engines": { "node": ">=10.0.0" } }, "node_modules/string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" @@ -14805,14 +13218,18 @@ }, "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/string-argv": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -14826,8 +13243,6 @@ "node_modules/string-width-cjs": { "name": "string-width", "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { @@ -14841,8 +13256,6 @@ }, "node_modules/stringify-entities": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", @@ -14855,8 +13268,6 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -14868,8 +13279,6 @@ "node_modules/strip-ansi-cjs": { "name": "strip-ansi", "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -14881,8 +13290,6 @@ }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -14894,14 +13301,10 @@ }, "node_modules/style-mod": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", - "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", "license": "MIT" }, "node_modules/style-to-js": { "version": "1.1.17", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", - "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", "license": "MIT", "dependencies": { "style-to-object": "1.0.9" @@ -14909,8 +13312,6 @@ }, "node_modules/style-to-object": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", - "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", "license": "MIT", "dependencies": { "inline-style-parser": "0.2.4" @@ -14918,8 +13319,6 @@ }, "node_modules/sumchecker": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -14931,8 +13330,6 @@ }, "node_modules/sumchecker/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": { @@ -14949,21 +13346,15 @@ }, "node_modules/sumchecker/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/super-media-element": { "version": "1.4.2", - "resolved": "https://registry.npmjs.org/super-media-element/-/super-media-element-1.4.2.tgz", - "integrity": "sha512-9pP/CVNp4NF2MNlRzLwQkjiTgKKe9WYXrLh9+8QokWmMxz+zt2mf1utkWLco26IuA3AfVcTb//qtlTIjY3VHxA==", "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -14989,9 +13380,9 @@ "license": "MIT" }, "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "license": "MIT", "engines": { "node": ">=6" @@ -15019,8 +13410,6 @@ }, "node_modules/tar-fs": { "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", - "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", "license": "MIT", "dependencies": { "chownr": "^1.1.1", @@ -15031,14 +13420,10 @@ }, "node_modules/tar-fs/node_modules/chownr": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "license": "ISC" }, "node_modules/tar-stream": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", "dependencies": { "bl": "^4.0.3", @@ -15053,8 +13438,6 @@ }, "node_modules/tar-stream/node_modules/readable-stream": { "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -15106,11 +13489,8 @@ }, "node_modules/temp": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" @@ -15121,8 +13501,6 @@ }, "node_modules/temp-file": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", - "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", "dev": true, "license": "MIT", "dependencies": { @@ -15132,8 +13510,6 @@ }, "node_modules/temp-file/node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15147,8 +13523,6 @@ }, "node_modules/temp-file/node_modules/jsonfile": { "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { @@ -15160,8 +13534,6 @@ }, "node_modules/temp-file/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { @@ -15170,11 +13542,8 @@ }, "node_modules/temp/node_modules/mkdirp": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -15184,12 +13553,8 @@ }, "node_modules/temp/node_modules/rimraf": { "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", - "peer": true, "dependencies": { "glob": "^7.1.3" }, @@ -15197,16 +13562,28 @@ "rimraf": "bin.js" } }, + "node_modules/text-extensions": { + "version": "2.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "dev": true, + "license": "MIT" + }, "node_modules/tiktok-video-element": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/tiktok-video-element/-/tiktok-video-element-0.1.1.tgz", - "integrity": "sha512-BaiVzvNz2UXDKTdSrXzrNf4q6Ecc+/utYUh7zdEu2jzYcJVDoqYbVfUl0bCfMoOeeAqg28vD/yN63Y3E9jOrlA==", "license": "MIT" }, "node_modules/tiny-async-pool": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz", - "integrity": "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==", "dev": true, "license": "MIT", "dependencies": { @@ -15215,8 +13592,6 @@ }, "node_modules/tiny-async-pool/node_modules/semver": { "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, "license": "ISC", "bin": { @@ -15225,14 +13600,15 @@ }, "node_modules/tiny-invariant": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.1", + "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -15247,8 +13623,6 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { "node": ">=12.0.0" @@ -15264,9 +13638,8 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -15276,8 +13649,6 @@ }, "node_modules/tmp": { "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", "dev": true, "license": "MIT", "engines": { @@ -15286,8 +13657,6 @@ }, "node_modules/tmp-promise": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15296,8 +13665,6 @@ }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -15309,8 +13676,6 @@ }, "node_modules/toidentifier": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "license": "MIT", "engines": { "node": ">=0.6" @@ -15318,8 +13683,6 @@ }, "node_modules/tree-kill": { "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true, "license": "MIT", "bin": { @@ -15328,8 +13691,6 @@ }, "node_modules/trim-lines": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", "funding": { "type": "github", @@ -15338,8 +13699,6 @@ }, "node_modules/trough": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", "license": "MIT", "funding": { "type": "github", @@ -15348,8 +13707,6 @@ }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, "license": "WTFPL", "dependencies": { @@ -15358,8 +13715,6 @@ }, "node_modules/ts-api-utils": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { @@ -15371,14 +13726,10 @@ }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/tunnel-agent": { "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "license": "Apache-2.0", "dependencies": { "safe-buffer": "^5.0.1" @@ -15389,20 +13740,14 @@ }, "node_modules/tweetnacl": { "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "license": "Unlicense" }, "node_modules/twitch-video-element": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/twitch-video-element/-/twitch-video-element-0.1.4.tgz", - "integrity": "sha512-SDpZ4f7sZmwHF6XG5PF0KWuP18pH/kNG04MhTcpqJby7Lk/D3TS/lCYd+RSg0rIAAVi1LDgSIo1yJs9kmHlhgw==", "license": "MIT" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -15414,8 +13759,6 @@ }, "node_modules/type-fest": { "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", "dev": true, "license": "(MIT OR CC0-1.0)", "optional": true, @@ -15428,8 +13771,6 @@ }, "node_modules/type-is": { "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "license": "MIT", "dependencies": { "media-typer": "0.3.0", @@ -15441,8 +13782,6 @@ }, "node_modules/type-is/node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -15450,8 +13789,6 @@ }, "node_modules/type-is/node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -15462,16 +13799,13 @@ }, "node_modules/typedarray": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "license": "MIT" }, "node_modules/typescript": { "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15482,8 +13816,6 @@ }, "node_modules/typescript-eslint": { "version": "8.45.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.45.0.tgz", - "integrity": "sha512-qzDmZw/Z5beNLUrXfd0HIW6MzIaAV5WNDxmMs9/3ojGOpYavofgNAAD/nC6tGV2PczIi0iw8vot2eAe/sBn7zg==", "dev": true, "license": "MIT", "dependencies": { @@ -15506,8 +13838,6 @@ }, "node_modules/ua-parser-js": { "version": "1.0.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", - "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", "funding": [ { "type": "opencollective", @@ -15532,14 +13862,21 @@ }, "node_modules/undici-types": { "version": "7.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.13.0.tgz", - "integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==", "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/unified": { "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -15557,8 +13894,6 @@ }, "node_modules/unique-filename": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", "dev": true, "license": "ISC", "dependencies": { @@ -15570,8 +13905,6 @@ }, "node_modules/unique-slug": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", "dev": true, "license": "ISC", "dependencies": { @@ -15583,8 +13916,6 @@ }, "node_modules/unist-util-is": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -15596,8 +13927,6 @@ }, "node_modules/unist-util-position": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -15609,8 +13938,6 @@ }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -15622,8 +13949,6 @@ }, "node_modules/unist-util-visit": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -15637,8 +13962,6 @@ }, "node_modules/unist-util-visit-parents": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -15651,8 +13974,6 @@ }, "node_modules/universalify": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", "engines": { @@ -15661,8 +13982,6 @@ }, "node_modules/unpipe": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "license": "MIT", "engines": { "node": ">= 0.8" @@ -15670,8 +13989,6 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -15680,8 +13997,6 @@ }, "node_modules/use-callback-ref": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", - "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" @@ -15701,8 +14016,6 @@ }, "node_modules/use-sidecar": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", - "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", "license": "MIT", "dependencies": { "detect-node-es": "^1.1.0", @@ -15721,56 +14034,33 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/utf8-byte-length": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", "dev": true, "license": "(WTFPL OR MIT)" }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, "node_modules/vary": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/vfile": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -15783,8 +14073,6 @@ }, "node_modules/vfile-message": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -15795,10 +14083,30 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, "node_modules/vimeo-video-element": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vimeo-video-element/-/vimeo-video-element-1.6.0.tgz", - "integrity": "sha512-Vs+WWvd6ph6FtY+DqrVO5OHUUS02An87QydUcCUtAsIiXnYhZl0yiDC0XxWiFluo+S6keG38i4xCaQfS1LgeSg==", "license": "MIT", "dependencies": { "@vimeo/player": "2.29.0" @@ -15806,9 +14114,8 @@ }, "node_modules/vite": { "version": "7.1.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.7.tgz", - "integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -15880,8 +14187,6 @@ }, "node_modules/vite/node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "license": "MIT", "engines": { "node": ">=12.0.0" @@ -15897,9 +14202,8 @@ }, "node_modules/vite/node_modules/picomatch": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -15909,8 +14213,6 @@ }, "node_modules/void-elements": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", "license": "MIT", "engines": { "node": ">=0.10.0" @@ -15918,14 +14220,10 @@ }, "node_modules/w3c-keyname": { "version": "2.2.8", - "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", - "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "license": "MIT" }, "node_modules/wait-on": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-9.0.1.tgz", - "integrity": "sha512-noeCAI+XbqWMXY23sKril0BSURhuLYarkVXwJv1uUWwoojZJE7pmX3vJ7kh7SZaNgPGzfsCSQIZM/AGvu0Q9pA==", "license": "MIT", "dependencies": { "axios": "^1.12.2", @@ -15943,8 +14241,6 @@ }, "node_modules/warning": { "version": "4.0.3", - "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", - "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" @@ -15952,8 +14248,6 @@ }, "node_modules/wcwidth": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, "license": "MIT", "dependencies": { @@ -15962,8 +14256,6 @@ }, "node_modules/weakmap-polyfill": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/weakmap-polyfill/-/weakmap-polyfill-2.0.4.tgz", - "integrity": "sha512-ZzxBf288iALJseijWelmECm/1x7ZwQn3sMYIkDr2VvZp7r6SEKuT8D0O9Wiq6L9Nl5mazrOMcmiZE/2NCenaxw==", "license": "MIT", "engines": { "node": ">=8.10.0" @@ -15971,8 +14263,6 @@ }, "node_modules/web-streams-polyfill": { "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "license": "MIT", "engines": { "node": ">= 8" @@ -15980,8 +14270,6 @@ }, "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": { @@ -15996,14 +14284,10 @@ }, "node_modules/which-module": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "license": "ISC" }, "node_modules/wistia-video-element": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/wistia-video-element/-/wistia-video-element-1.3.4.tgz", - "integrity": "sha512-2l22oaQe4jUfi3yvsh2m2oCEgvbqTzaSYx6aJnZAvV5hlMUJlyZheFUnaj0JU2wGlHdVGV7xNY+5KpKu+ruLYA==", "license": "MIT", "dependencies": { "super-media-element": "~1.4.2" @@ -16011,8 +14295,6 @@ }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { @@ -16021,8 +14303,6 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -16040,8 +14320,6 @@ "node_modules/wrap-ansi-cjs": { "name": "wrap-ansi", "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { @@ -16058,14 +14336,10 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, "node_modules/ws": { "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -16085,8 +14359,6 @@ }, "node_modules/xmlbuilder": { "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true, "license": "MIT", "engines": { @@ -16095,8 +14367,6 @@ }, "node_modules/xtend": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "license": "MIT", "engines": { "node": ">=0.4" @@ -16104,8 +14374,6 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { @@ -16114,15 +14382,22 @@ }, "node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.1", + "devOptional": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + } + }, "node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", "dependencies": { @@ -16140,8 +14415,6 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { @@ -16150,8 +14423,6 @@ }, "node_modules/yauzl": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "license": "MIT", "dependencies": { @@ -16161,8 +14432,6 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { @@ -16174,14 +14443,10 @@ }, "node_modules/youtube-video-element": { "version": "1.6.2", - "resolved": "https://registry.npmjs.org/youtube-video-element/-/youtube-video-element-1.6.2.tgz", - "integrity": "sha512-YHDIOAqgRpfl1Ois9HcB8UFtWOxK8KJrV5TXpImj4BKYP1rWT04f/fMM9tQ9SYZlBKukT7NR+9wcI3UpB5BMDQ==", "license": "MIT" }, "node_modules/zod": { "version": "4.1.11", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.11.tgz", - "integrity": "sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" @@ -16189,8 +14454,6 @@ }, "node_modules/zwitch": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", "license": "MIT", "funding": { "type": "github", diff --git a/package.json b/package.json index 8b834d2f..b4b8af5c 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,18 @@ { "name": "termix", "private": true, - "version": "1.7.3", + "version": "1.8.0", "description": "A web-based server management platform with SSH terminal, tunneling, and file editing capabilities", "author": "Karmaa", "main": "electron/main.cjs", "type": "module", "scripts": { "clean": "npx prettier . --write", + "format": "prettier --write .", + "format:check": "prettier --check .", + "lint": "eslint .", + "lint:fix": "eslint --fix .", + "type-check": "tsc --noEmit", "dev": "vite", "build": "vite build && tsc -p tsconfig.node.json", "build:backend": "tsc -p tsconfig.node.json", @@ -19,8 +24,10 @@ "build:linux-portable": "npm run build && electron-builder --linux --dir", "build:linux-appimage": "npm run build && electron-builder --linux AppImage", "build:linux-targz": "npm run build && electron-builder --linux tar.gz", + "build:mac": "npm run build && electron-builder --mac --universal", "test:encryption": "tsc -p tsconfig.node.json && node ./dist/backend/backend/utils/encryption-test.js", - "migrate:encryption": "tsc -p tsconfig.node.json && node ./dist/backend/backend/utils/encryption-migration.js" + "migrate:encryption": "tsc -p tsconfig.node.json && node ./dist/backend/backend/utils/encryption-migration.js", + "prepare": "husky" }, "dependencies": { "@codemirror/autocomplete": "^6.18.7", @@ -44,7 +51,7 @@ "@radix-ui/react-switch": "^1.2.5", "@radix-ui/react-tabs": "^1.1.12", "@radix-ui/react-tooltip": "^1.2.8", - "@tailwindcss/vite": "^4.1.11", + "@tailwindcss/vite": "^4.1.14", "@types/bcryptjs": "^2.4.6", "@types/cookie-parser": "^1.4.9", "@types/jszip": "^3.4.0", @@ -95,16 +102,21 @@ "react-simple-keyboard": "^3.8.120", "react-syntax-highlighter": "^15.6.6", "react-xtermjs": "^1.0.10", + "recharts": "^3.2.1", "remark-gfm": "^4.0.1", "sonner": "^2.0.7", "speakeasy": "^2.0.0", "ssh2": "^1.16.0", "tailwind-merge": "^3.3.1", + "tailwindcss": "^4.1.14", "wait-on": "^9.0.1", "ws": "^8.18.3", "zod": "^4.0.5" }, "devDependencies": { + "@commitlint/cli": "^20.1.0", + "@commitlint/config-conventional": "^20.0.0", + "@electron/notarize": "^2.5.0", "@eslint/js": "^9.34.0", "@types/better-sqlite3": "^7.6.13", "@types/cors": "^2.8.19", @@ -123,9 +135,19 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.3.0", + "husky": "^9.1.7", + "lint-staged": "^16.2.3", "prettier": "3.6.2", "typescript": "~5.9.2", "typescript-eslint": "^8.40.0", "vite": "^7.1.5" + }, + "lint-staged": { + "*.{js,jsx,ts,tsx}": [ + "prettier --write" + ], + "*.{json,css,md}": [ + "prettier --write" + ] } } diff --git a/public/icon.icns b/public/icon.icns index 8a97f2ae..49e22cfc 100644 Binary files a/public/icon.icns and b/public/icon.icns differ diff --git a/src/backend/database/database.ts b/src/backend/database/database.ts index 60549725..bdfe0f03 100644 --- a/src/backend/database/database.ts +++ b/src/backend/database/database.ts @@ -6,6 +6,7 @@ import userRoutes from "./routes/users.js"; import sshRoutes from "./routes/ssh.js"; import alertRoutes from "./routes/alerts.js"; import credentialsRoutes from "./routes/credentials.js"; +import snippetsRoutes from "./routes/snippets.js"; import cors from "cors"; import fetch from "node-fetch"; import fs from "fs"; @@ -31,6 +32,12 @@ import { sshCredentialUsage, settings, } from "./db/schema.js"; +import type { + CacheEntry, + GitHubRelease, + GitHubAPIResponse, + AuthenticatedRequest, +} from "../../types/index.js"; import { getDb } from "./db/index.js"; import Database from "better-sqlite3"; @@ -105,17 +112,11 @@ const upload = multer({ }, }); -interface CacheEntry { - data: any; - timestamp: number; - expiresAt: number; -} - class GitHubCache { private cache: Map = new Map(); private readonly CACHE_DURATION = 30 * 60 * 1000; - set(key: string, data: any): void { + set(key: string, data: T): void { const now = Date.now(); this.cache.set(key, { data, @@ -124,7 +125,7 @@ class GitHubCache { }); } - get(key: string): any | null { + get(key: string): T | null { const entry = this.cache.get(key); if (!entry) { return null; @@ -135,7 +136,7 @@ class GitHubCache { return null; } - return entry.data; + return entry.data as T; } } @@ -145,34 +146,16 @@ const GITHUB_API_BASE = "https://api.github.com"; const REPO_OWNER = "Termix-SSH"; const REPO_NAME = "Termix"; -interface GitHubRelease { - id: number; - tag_name: string; - name: string; - body: string; - published_at: string; - html_url: string; - assets: Array<{ - id: number; - name: string; - size: number; - download_count: number; - browser_download_url: string; - }>; - prerelease: boolean; - draft: boolean; -} - -async function fetchGitHubAPI( +async function fetchGitHubAPI( endpoint: string, cacheKey: string, -): Promise { - const cachedData = githubCache.get(cacheKey); - if (cachedData) { +): Promise> { + const cachedEntry = githubCache.get>(cacheKey); + if (cachedEntry) { return { - data: cachedData, + data: cachedEntry.data, cached: true, - cache_age: Date.now() - cachedData.timestamp, + cache_age: Date.now() - cachedEntry.timestamp, }; } @@ -191,8 +174,13 @@ async function fetchGitHubAPI( ); } - const data = await response.json(); - githubCache.set(cacheKey, data); + const data = (await response.json()) as T; + const cacheData: CacheEntry = { + data, + timestamp: Date.now(), + expiresAt: Date.now() + 30 * 60 * 1000, + }; + githubCache.set(cacheKey, cacheData); return { data: data, @@ -257,7 +245,7 @@ app.get("/version", authenticateJWT, async (req, res) => { localVersion = foundVersion; break; } - } catch (error) { + } catch { continue; } } @@ -272,7 +260,7 @@ app.get("/version", authenticateJWT, async (req, res) => { try { const cacheKey = "latest_release"; - const releaseData = await fetchGitHubAPI( + const releaseData = await fetchGitHubAPI( `/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest`, cacheKey, ); @@ -323,12 +311,12 @@ app.get("/releases/rss", authenticateJWT, async (req, res) => { ); const cacheKey = `releases_rss_${page}_${per_page}`; - const releasesData = await fetchGitHubAPI( + const releasesData = await fetchGitHubAPI( `/repos/${REPO_OWNER}/${REPO_NAME}/releases?page=${page}&per_page=${per_page}`, cacheKey, ); - const rssItems = releasesData.data.map((release: GitHubRelease) => ({ + const rssItems = releasesData.data.map((release) => ({ id: release.id, title: release.name || release.tag_name, description: release.body, @@ -372,7 +360,6 @@ app.get("/releases/rss", authenticateJWT, async (req, res) => { app.get("/encryption/status", requireAdmin, async (req, res) => { try { - const authManager = AuthManager.getInstance(); const securityStatus = { initialized: true, system: { hasSecret: true, isValid: true }, @@ -417,8 +404,6 @@ app.post("/encryption/initialize", requireAdmin, async (req, res) => { app.post("/encryption/regenerate", requireAdmin, async (req, res) => { try { - const authManager = AuthManager.getInstance(); - apiLogger.warn("System JWT secret regenerated via API", { operation: "jwt_regenerate_api", }); @@ -440,8 +425,6 @@ app.post("/encryption/regenerate", requireAdmin, async (req, res) => { app.post("/encryption/regenerate-jwt", requireAdmin, async (req, res) => { try { - const authManager = AuthManager.getInstance(); - apiLogger.warn("JWT secret regenerated via API", { operation: "jwt_secret_regenerate_api", }); @@ -462,7 +445,7 @@ app.post("/encryption/regenerate-jwt", requireAdmin, async (req, res) => { app.post("/database/export", authenticateJWT, async (req, res) => { try { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { password } = req.body; if (!password) { @@ -695,7 +678,7 @@ app.post("/database/export", authenticateJWT, async (req, res) => { decrypted.authType, decrypted.password || null, decrypted.key || null, - decrypted.keyPassword || null, + decrypted.key_password || null, decrypted.keyType || null, decrypted.autostartPassword || null, decrypted.autostartKey || null, @@ -738,9 +721,9 @@ app.post("/database/export", authenticateJWT, async (req, res) => { decrypted.username, decrypted.password || null, decrypted.key || null, - decrypted.privateKey || null, - decrypted.publicKey || null, - decrypted.keyPassword || null, + decrypted.private_key || null, + decrypted.public_key || null, + decrypted.key_password || null, decrypted.keyType || null, decrypted.detectedKeyType || null, decrypted.usageCount || 0, @@ -916,7 +899,7 @@ app.post( return res.status(400).json({ error: "No file uploaded" }); } - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { password } = req.body; const mainDb = getDb(); @@ -998,7 +981,7 @@ app.post( try { importDb = new Database(req.file.path, { readonly: true }); - const tables = importDb + importDb .prepare("SELECT name FROM sqlite_master WHERE type='table'") .all(); } catch (sqliteError) { @@ -1088,7 +1071,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info("ssh_data table not found in import file, skipping"); } @@ -1149,7 +1132,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info( "ssh_credentials table not found in import file, skipping", ); @@ -1220,7 +1203,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info(`${table} table not found in import file, skipping`); } } @@ -1258,7 +1241,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info( "dismissed_alerts table not found in import file, skipping", ); @@ -1299,7 +1282,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info("settings table not found in import file, skipping"); } } else { @@ -1317,7 +1300,7 @@ app.post( try { fs.unlinkSync(req.file.path); - } catch (cleanupError) { + } catch { apiLogger.warn("Failed to clean up uploaded file", { operation: "file_cleanup_warning", filePath: req.file.path, @@ -1343,7 +1326,7 @@ app.post( if (req.file?.path && fs.existsSync(req.file.path)) { try { fs.unlinkSync(req.file.path); - } catch (cleanupError) { + } catch { apiLogger.warn("Failed to clean up uploaded file after error", { operation: "file_cleanup_error", filePath: req.file.path, @@ -1353,7 +1336,7 @@ app.post( apiLogger.error("SQLite import failed", error, { operation: "sqlite_import_api_failed", - userId: (req as any).userId, + userId: (req as AuthenticatedRequest).userId, }); res.status(500).json({ error: "Failed to import SQLite data", @@ -1365,12 +1348,8 @@ app.post( app.post("/database/export/preview", authenticateJWT, async (req, res) => { try { - const userId = (req as any).userId; - const { - format = "encrypted", - scope = "user_data", - includeCredentials = true, - } = req.body; + const userId = (req as AuthenticatedRequest).userId; + const { scope = "user_data", includeCredentials = true } = req.body; const exportData = await UserDataExport.exportUserData(userId, { format: "encrypted", @@ -1440,13 +1419,15 @@ app.use("/users", userRoutes); app.use("/ssh", sshRoutes); app.use("/alerts", alertRoutes); app.use("/credentials", credentialsRoutes); +app.use("/snippets", snippetsRoutes); app.use( ( err: unknown, req: express.Request, res: express.Response, - next: express.NextFunction, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _next: express.NextFunction, ) => { apiLogger.error("Unhandled error in request", err, { operation: "error_handler", @@ -1459,7 +1440,6 @@ app.use( ); const HTTP_PORT = 30001; -const HTTPS_PORT = process.env.SSL_PORT || 8443; async function initializeSecurity() { try { @@ -1472,13 +1452,6 @@ async function initializeSecurity() { if (!isValid) { throw new Error("Security system validation failed"); } - - const securityStatus = { - initialized: true, - system: { hasSecret: true, isValid: true }, - activeSessions: {}, - activeSessionCount: 0, - }; } catch (error) { databaseLogger.error("Failed to initialize security system", error, { operation: "security_init_error", @@ -1510,13 +1483,17 @@ app.get( if (status.hasUnencryptedDb) { try { unencryptedSize = fs.statSync(dbPath).size; - } catch (error) {} + } catch { + // Ignore file access errors + } } if (status.hasEncryptedDb) { try { encryptedSize = fs.statSync(encryptedDbPath).size; - } catch (error) {} + } catch { + // Ignore file access errors + } } res.json({ diff --git a/src/backend/database/db/index.ts b/src/backend/database/db/index.ts index 88cca125..c5e44bc3 100644 --- a/src/backend/database/db/index.ts +++ b/src/backend/database/db/index.ts @@ -23,7 +23,7 @@ const enableFileEncryption = process.env.DB_FILE_ENCRYPTION !== "false"; const dbPath = path.join(dataDir, "db.sqlite"); const encryptedDbPath = `${dbPath}.encrypted`; -let actualDbPath = ":memory:"; +const actualDbPath = ":memory:"; let memoryDatabase: Database.Database; let isNewDatabase = false; let sqlite: Database.Database; @@ -31,7 +31,8 @@ let sqlite: Database.Database; async function initializeDatabaseAsync(): Promise { const systemCrypto = SystemCrypto.getInstance(); - const dbKey = await systemCrypto.getDatabaseKey(); + // Ensure database key is initialized + await systemCrypto.getDatabaseKey(); if (enableFileEncryption) { try { if (DatabaseFileEncryption.isEncryptedDatabaseFile(encryptedDbPath)) { @@ -165,6 +166,7 @@ async function initializeCompleteDatabase(): Promise { tunnel_connections TEXT, enable_file_manager INTEGER NOT NULL DEFAULT 1, default_path TEXT, + stats_config TEXT, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users (id) @@ -242,6 +244,28 @@ async function initializeCompleteDatabase(): Promise { FOREIGN KEY (user_id) REFERENCES users (id) ); + CREATE TABLE IF NOT EXISTS snippets ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id TEXT NOT NULL, + name TEXT NOT NULL, + content TEXT NOT NULL, + description TEXT, + created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users (id) + ); + + CREATE TABLE IF NOT EXISTS recent_activity ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id TEXT NOT NULL, + type TEXT NOT NULL, + host_id INTEGER NOT NULL, + host_name TEXT NOT NULL, + timestamp TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users (id), + FOREIGN KEY (host_id) REFERENCES ssh_data (id) + ); + `); migrateSchema(); @@ -277,7 +301,7 @@ const addColumnIfNotExists = ( FROM ${table} LIMIT 1`, ) .get(); - } catch (e) { + } catch { try { sqlite.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition};`); @@ -361,6 +385,7 @@ const migrateSchema = () => { addColumnIfNotExists("ssh_data", "autostart_password", "TEXT"); addColumnIfNotExists("ssh_data", "autostart_key", "TEXT"); addColumnIfNotExists("ssh_data", "autostart_key_password", "TEXT"); + addColumnIfNotExists("ssh_data", "stats_config", "TEXT"); addColumnIfNotExists("ssh_credentials", "private_key", "TEXT"); addColumnIfNotExists("ssh_credentials", "public_key", "TEXT"); @@ -476,21 +501,29 @@ async function cleanupDatabase() { for (const file of files) { try { fs.unlinkSync(path.join(tempDir, file)); - } catch {} + } catch { + // Ignore cleanup errors + } } try { fs.rmdirSync(tempDir); - } catch {} + } catch { + // Ignore cleanup errors + } } - } catch (error) {} + } catch { + // Ignore cleanup errors + } } process.on("exit", () => { if (sqlite) { try { sqlite.close(); - } catch {} + } catch { + // Ignore close errors on exit + } } }); diff --git a/src/backend/database/db/schema.ts b/src/backend/database/db/schema.ts index eeac5c34..46cbb7f9 100644 --- a/src/backend/database/db/schema.ts +++ b/src/backend/database/db/schema.ts @@ -65,6 +65,7 @@ export const sshData = sqliteTable("ssh_data", { .notNull() .default(true), defaultPath: text("default_path"), + statsConfig: text("stats_config"), createdAt: text("created_at") .notNull() .default(sql`CURRENT_TIMESTAMP`), @@ -172,3 +173,34 @@ export const sshCredentialUsage = sqliteTable("ssh_credential_usage", { .notNull() .default(sql`CURRENT_TIMESTAMP`), }); + +export const snippets = sqliteTable("snippets", { + id: integer("id").primaryKey({ autoIncrement: true }), + userId: text("user_id") + .notNull() + .references(() => users.id), + name: text("name").notNull(), + content: text("content").notNull(), + description: text("description"), + createdAt: text("created_at") + .notNull() + .default(sql`CURRENT_TIMESTAMP`), + updatedAt: text("updated_at") + .notNull() + .default(sql`CURRENT_TIMESTAMP`), +}); + +export const recentActivity = sqliteTable("recent_activity", { + id: integer("id").primaryKey({ autoIncrement: true }), + userId: text("user_id") + .notNull() + .references(() => users.id), + type: text("type").notNull(), + hostId: integer("host_id") + .notNull() + .references(() => sshData.id), + hostName: text("host_name").notNull(), + timestamp: text("timestamp") + .notNull() + .default(sql`CURRENT_TIMESTAMP`), +}); diff --git a/src/backend/database/routes/alerts.ts b/src/backend/database/routes/alerts.ts index e0e01f1c..cf653109 100644 --- a/src/backend/database/routes/alerts.ts +++ b/src/backend/database/routes/alerts.ts @@ -1,3 +1,8 @@ +import type { + AuthenticatedRequest, + CacheEntry, + TermixAlert, +} from "../../../types/index.js"; import express from "express"; import { db } from "../db/index.js"; import { dismissedAlerts } from "../db/schema.js"; @@ -6,17 +11,11 @@ import fetch from "node-fetch"; import { authLogger } from "../../utils/logger.js"; import { AuthManager } from "../../utils/auth-manager.js"; -interface CacheEntry { - data: any; - timestamp: number; - expiresAt: number; -} - class AlertCache { private cache: Map = new Map(); private readonly CACHE_DURATION = 5 * 60 * 1000; - set(key: string, data: any): void { + set(key: string, data: T): void { const now = Date.now(); this.cache.set(key, { data, @@ -25,7 +24,7 @@ class AlertCache { }); } - get(key: string): any | null { + get(key: string): T | null { const entry = this.cache.get(key); if (!entry) { return null; @@ -36,7 +35,7 @@ class AlertCache { return null; } - return entry.data; + return entry.data as T; } } @@ -47,20 +46,9 @@ const REPO_OWNER = "Termix-SSH"; const REPO_NAME = "Docs"; const ALERTS_FILE = "main/termix-alerts.json"; -interface TermixAlert { - id: string; - title: string; - message: string; - expiresAt: string; - priority?: "low" | "medium" | "high" | "critical"; - type?: "info" | "warning" | "error" | "success"; - actionUrl?: string; - actionText?: string; -} - async function fetchAlertsFromGitHub(): Promise { const cacheKey = "termix_alerts"; - const cachedData = alertCache.get(cacheKey); + const cachedData = alertCache.get(cacheKey); if (cachedData) { return cachedData; } @@ -115,7 +103,7 @@ const authenticateJWT = authManager.createAuthMiddleware(); // GET /alerts router.get("/", authenticateJWT, async (req, res) => { try { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const allAlerts = await fetchAlertsFromGitHub(); @@ -148,7 +136,7 @@ router.get("/", authenticateJWT, async (req, res) => { router.post("/dismiss", authenticateJWT, async (req, res) => { try { const { alertId } = req.body; - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!alertId) { authLogger.warn("Missing alertId in dismiss request", { userId }); @@ -170,7 +158,7 @@ router.post("/dismiss", authenticateJWT, async (req, res) => { return res.status(409).json({ error: "Alert already dismissed" }); } - const result = await db.insert(dismissedAlerts).values({ + await db.insert(dismissedAlerts).values({ userId, alertId, }); @@ -186,7 +174,7 @@ router.post("/dismiss", authenticateJWT, async (req, res) => { // GET /alerts/dismissed/:userId router.get("/dismissed", authenticateJWT, async (req, res) => { try { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const dismissedAlertRecords = await db .select({ @@ -211,7 +199,7 @@ router.get("/dismissed", authenticateJWT, async (req, res) => { router.delete("/dismiss", authenticateJWT, async (req, res) => { try { const { alertId } = req.body; - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!alertId) { return res.status(400).json({ error: "Alert ID is required" }); diff --git a/src/backend/database/routes/credentials.ts b/src/backend/database/routes/credentials.ts index c856322f..2f0c3ce4 100644 --- a/src/backend/database/routes/credentials.ts +++ b/src/backend/database/routes/credentials.ts @@ -1,16 +1,15 @@ +import type { AuthenticatedRequest } from "../../../types/index.js"; import express from "express"; import { db } from "../db/index.js"; import { sshCredentials, sshCredentialUsage, sshData } from "../db/schema.js"; import { eq, and, desc, sql } from "drizzle-orm"; -import type { Request, Response, NextFunction } from "express"; -import jwt from "jsonwebtoken"; +import type { Request, Response } from "express"; import { authLogger } from "../../utils/logger.js"; import { SimpleDBOps } from "../../utils/simple-db-ops.js"; import { AuthManager } from "../../utils/auth-manager.js"; import { parseSSHKey, parsePublicKey, - detectKeyType, validateKeyPair, } from "../../utils/ssh-key-utils.js"; import crypto from "crypto"; @@ -29,7 +28,11 @@ function generateSSHKeyPair( } { try { let ssh2Type = keyType; - const options: any = {}; + const options: { + bits?: number; + passphrase?: string; + cipher?: string; + } = {}; if (keyType === "ssh-rsa") { ssh2Type = "rsa"; @@ -46,6 +49,7 @@ function generateSSHKeyPair( options.cipher = "aes128-cbc"; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const keyPair = ssh2Utils.generateKeyPairSync(ssh2Type as any, options); return { @@ -64,7 +68,7 @@ function generateSSHKeyPair( const router = express.Router(); -function isNonEmptyString(val: any): val is string { +function isNonEmptyString(val: unknown): val is string { return typeof val === "string" && val.trim().length > 0; } @@ -79,7 +83,7 @@ router.post( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { name, description, @@ -226,7 +230,7 @@ router.get( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!isNonEmptyString(userId)) { authLogger.warn("Invalid userId for credential fetch"); @@ -259,7 +263,7 @@ router.get( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!isNonEmptyString(userId)) { authLogger.warn("Invalid userId for credential folder fetch"); @@ -297,7 +301,7 @@ router.get( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { id } = req.params; if (!isNonEmptyString(userId) || !id) { @@ -328,19 +332,19 @@ router.get( const output = formatCredentialOutput(credential); if (credential.password) { - (output as any).password = credential.password; + output.password = credential.password; } if (credential.key) { - (output as any).key = credential.key; + output.key = credential.key; } if (credential.private_key) { - (output as any).privateKey = credential.private_key; + output.privateKey = credential.private_key; } if (credential.public_key) { - (output as any).publicKey = credential.public_key; + output.publicKey = credential.public_key; } if (credential.key_password) { - (output as any).keyPassword = credential.key_password; + output.keyPassword = credential.key_password; } res.json(output); @@ -361,7 +365,7 @@ router.put( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { id } = req.params; const updateData = req.body; @@ -385,7 +389,7 @@ router.put( return res.status(404).json({ error: "Credential not found" }); } - const updateFields: any = {}; + const updateFields: Record = {}; if (updateData.name !== undefined) updateFields.name = updateData.name.trim(); @@ -497,7 +501,7 @@ router.delete( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { id } = req.params; if (!isNonEmptyString(userId) || !id) { @@ -596,7 +600,7 @@ router.post( "/:id/apply-to-host/:hostId", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { id: credentialId, hostId } = req.params; if (!isNonEmptyString(userId) || !credentialId || !hostId) { @@ -629,8 +633,8 @@ router.post( .update(sshData) .set({ credentialId: parseInt(credentialId), - username: credential.username, - authType: credential.auth_type || credential.authType, + username: credential.username as string, + authType: (credential.auth_type || credential.authType) as string, password: null, key: null, key_password: null, @@ -675,7 +679,7 @@ router.get( "/:id/hosts", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { id: credentialId } = req.params; if (!isNonEmptyString(userId) || !credentialId) { @@ -707,7 +711,9 @@ router.get( }, ); -function formatCredentialOutput(credential: any): any { +function formatCredentialOutput( + credential: Record, +): Record { return { id: credential.id, name: credential.name, @@ -731,7 +737,9 @@ function formatCredentialOutput(credential: any): any { }; } -function formatSSHHostOutput(host: any): any { +function formatSSHHostOutput( + host: Record, +): Record { return { id: host.id, userId: host.userId, @@ -751,7 +759,7 @@ function formatSSHHostOutput(host: any): any { enableTerminal: !!host.enableTerminal, enableTunnel: !!host.enableTunnel, tunnelConnections: host.tunnelConnections - ? JSON.parse(host.tunnelConnections) + ? JSON.parse(host.tunnelConnections as string) : [], enableFileManager: !!host.enableFileManager, defaultPath: host.defaultPath, @@ -766,7 +774,7 @@ router.put( "/folders/rename", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { oldName, newName } = req.body; if (!isNonEmptyString(oldName) || !isNonEmptyString(newName)) { @@ -970,7 +978,7 @@ router.post( try { let privateKeyObj; - let parseAttempts = []; + const parseAttempts = []; try { privateKeyObj = crypto.createPrivateKey({ @@ -1093,7 +1101,9 @@ router.post( finalPublicKey = `${keyType} ${base64Data}`; formatType = "ssh"; } - } catch (sshError) {} + } catch { + // Ignore validation errors + } const response = { success: true, @@ -1117,15 +1127,15 @@ router.post( ); async function deploySSHKeyToHost( - hostConfig: any, + hostConfig: Record, publicKey: string, - credentialData: any, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _credentialData: Record, ): Promise<{ success: boolean; message?: string; error?: string }> { return new Promise((resolve) => { const conn = new Client(); - let connectionTimeout: NodeJS.Timeout; - connectionTimeout = setTimeout(() => { + const connectionTimeout = setTimeout(() => { conn.destroy(); resolve({ success: false, error: "Connection timeout" }); }, 120000); @@ -1158,7 +1168,9 @@ async function deploySSHKeyToHost( } }); - stream.on("data", (data) => {}); + stream.on("data", () => { + // Ignore output + }); }, ); }); @@ -1175,7 +1187,9 @@ async function deploySSHKeyToHost( if (parsed.data) { actualPublicKey = parsed.data; } - } catch (e) {} + } catch { + // Ignore parse errors + } const keyParts = actualPublicKey.trim().split(" "); if (keyParts.length < 2) { @@ -1202,7 +1216,7 @@ async function deploySSHKeyToHost( output += data.toString(); }); - stream.on("close", (code) => { + stream.on("close", () => { clearTimeout(checkTimeout); const exists = output.trim() === "0"; resolveCheck(exists); @@ -1229,7 +1243,9 @@ async function deploySSHKeyToHost( if (parsed.data) { actualPublicKey = parsed.data; } - } catch (e) {} + } catch { + // Ignore parse errors + } const escapedKey = actualPublicKey .replace(/\\/g, "\\\\") @@ -1269,7 +1285,9 @@ async function deploySSHKeyToHost( if (parsed.data) { actualPublicKey = parsed.data; } - } catch (e) {} + } catch { + // Ignore parse errors + } const keyParts = actualPublicKey.trim().split(" "); if (keyParts.length < 2) { @@ -1295,7 +1313,7 @@ async function deploySSHKeyToHost( output += data.toString(); }); - stream.on("close", (code) => { + stream.on("close", () => { clearTimeout(verifyTimeout); const verified = output.trim() === "0"; resolveVerify(verified); @@ -1356,7 +1374,7 @@ async function deploySSHKeyToHost( }); try { - const connectionConfig: any = { + const connectionConfig: Record = { host: hostConfig.ip, port: hostConfig.port || 22, username: hostConfig.username, @@ -1403,14 +1421,15 @@ async function deploySSHKeyToHost( connectionConfig.password = hostConfig.password; } else if (hostConfig.authType === "key" && hostConfig.privateKey) { try { + const privateKey = hostConfig.privateKey as string; if ( - !hostConfig.privateKey.includes("-----BEGIN") || - !hostConfig.privateKey.includes("-----END") + !privateKey.includes("-----BEGIN") || + !privateKey.includes("-----END") ) { throw new Error("Invalid private key format"); } - const cleanKey = hostConfig.privateKey + const cleanKey = privateKey .trim() .replace(/\r\n/g, "\n") .replace(/\r/g, "\n"); @@ -1465,7 +1484,7 @@ router.post( } try { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!userId) { return res.status(401).json({ success: false, @@ -1521,7 +1540,7 @@ router.post( const hostData = targetHost[0]; - let hostConfig = { + const hostConfig = { ip: hostData.ip, port: hostData.port, username: hostData.username, @@ -1532,7 +1551,7 @@ router.post( }; if (hostData.authType === "credential" && hostData.credentialId) { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!userId) { return res.status(400).json({ success: false, @@ -1546,7 +1565,7 @@ router.post( db .select() .from(sshCredentials) - .where(eq(sshCredentials.id, hostData.credentialId)) + .where(eq(sshCredentials.id, hostData.credentialId as number)) .limit(1), "ssh_credentials", userId, @@ -1571,7 +1590,7 @@ router.post( error: "Host credential not found", }); } - } catch (error) { + } catch { return res.status(500).json({ success: false, error: "Failed to resolve host credentials", @@ -1581,7 +1600,7 @@ router.post( const deployResult = await deploySSHKeyToHost( hostConfig, - credData.publicKey, + credData.publicKey as string, credData, ); diff --git a/src/backend/database/routes/snippets.ts b/src/backend/database/routes/snippets.ts new file mode 100644 index 00000000..89dc4513 --- /dev/null +++ b/src/backend/database/routes/snippets.ts @@ -0,0 +1,260 @@ +import type { AuthenticatedRequest } from "../../../types/index.js"; +import express from "express"; +import { db } from "../db/index.js"; +import { snippets } from "../db/schema.js"; +import { eq, and, desc, sql } from "drizzle-orm"; +import type { Request, Response } from "express"; +import { authLogger } from "../../utils/logger.js"; +import { AuthManager } from "../../utils/auth-manager.js"; + +const router = express.Router(); + +function isNonEmptyString(val: unknown): val is string { + return typeof val === "string" && val.trim().length > 0; +} + +const authManager = AuthManager.getInstance(); +const authenticateJWT = authManager.createAuthMiddleware(); +const requireDataAccess = authManager.createDataAccessMiddleware(); + +// Get all snippets for the authenticated user +// GET /snippets +router.get( + "/", + authenticateJWT, + requireDataAccess, + async (req: Request, res: Response) => { + const userId = (req as AuthenticatedRequest).userId; + + if (!isNonEmptyString(userId)) { + authLogger.warn("Invalid userId for snippets fetch"); + return res.status(400).json({ error: "Invalid userId" }); + } + + try { + const result = await db + .select() + .from(snippets) + .where(eq(snippets.userId, userId)) + .orderBy(desc(snippets.updatedAt)); + + res.json(result); + } catch (err) { + authLogger.error("Failed to fetch snippets", err); + res.status(500).json({ error: "Failed to fetch snippets" }); + } + }, +); + +// Get a specific snippet by ID +// GET /snippets/:id +router.get( + "/:id", + authenticateJWT, + requireDataAccess, + async (req: Request, res: Response) => { + const userId = (req as AuthenticatedRequest).userId; + const { id } = req.params; + const snippetId = parseInt(id, 10); + + if (!isNonEmptyString(userId) || isNaN(snippetId)) { + authLogger.warn("Invalid request for snippet fetch: invalid ID", { + userId, + id, + }); + return res.status(400).json({ error: "Invalid request parameters" }); + } + + try { + const result = await db + .select() + .from(snippets) + .where(and(eq(snippets.id, parseInt(id)), eq(snippets.userId, userId))); + + if (result.length === 0) { + return res.status(404).json({ error: "Snippet not found" }); + } + + res.json(result[0]); + } catch (err) { + authLogger.error("Failed to fetch snippet", err); + res.status(500).json({ + error: err instanceof Error ? err.message : "Failed to fetch snippet", + }); + } + }, +); + +// Create a new snippet +// POST /snippets +router.post( + "/", + authenticateJWT, + requireDataAccess, + async (req: Request, res: Response) => { + const userId = (req as AuthenticatedRequest).userId; + const { name, content, description } = req.body; + + if ( + !isNonEmptyString(userId) || + !isNonEmptyString(name) || + !isNonEmptyString(content) + ) { + authLogger.warn("Invalid snippet creation data validation failed", { + operation: "snippet_create", + userId, + hasName: !!name, + hasContent: !!content, + }); + return res.status(400).json({ error: "Name and content are required" }); + } + + try { + const insertData = { + userId, + name: name.trim(), + content: content.trim(), + description: description?.trim() || null, + }; + + const result = await db.insert(snippets).values(insertData).returning(); + + authLogger.success(`Snippet created: ${name} by user ${userId}`, { + operation: "snippet_create_success", + userId, + snippetId: result[0].id, + name, + }); + + res.status(201).json(result[0]); + } catch (err) { + authLogger.error("Failed to create snippet", err); + res.status(500).json({ + error: err instanceof Error ? err.message : "Failed to create snippet", + }); + } + }, +); + +// Update a snippet +// PUT /snippets/:id +router.put( + "/:id", + authenticateJWT, + requireDataAccess, + async (req: Request, res: Response) => { + const userId = (req as AuthenticatedRequest).userId; + const { id } = req.params; + const updateData = req.body; + + if (!isNonEmptyString(userId) || !id) { + authLogger.warn("Invalid request for snippet update"); + return res.status(400).json({ error: "Invalid request" }); + } + + try { + const existing = await db + .select() + .from(snippets) + .where(and(eq(snippets.id, parseInt(id)), eq(snippets.userId, userId))); + + if (existing.length === 0) { + return res.status(404).json({ error: "Snippet not found" }); + } + + const updateFields: Partial<{ + updatedAt: ReturnType; + name: string; + content: string; + description: string | null; + }> = { + updatedAt: sql`CURRENT_TIMESTAMP`, + }; + + if (updateData.name !== undefined) + updateFields.name = updateData.name.trim(); + if (updateData.content !== undefined) + updateFields.content = updateData.content.trim(); + if (updateData.description !== undefined) + updateFields.description = updateData.description?.trim() || null; + + await db + .update(snippets) + .set(updateFields) + .where(and(eq(snippets.id, parseInt(id)), eq(snippets.userId, userId))); + + const updated = await db + .select() + .from(snippets) + .where(eq(snippets.id, parseInt(id))); + + authLogger.success( + `Snippet updated: ${updated[0].name} by user ${userId}`, + { + operation: "snippet_update_success", + userId, + snippetId: parseInt(id), + name: updated[0].name, + }, + ); + + res.json(updated[0]); + } catch (err) { + authLogger.error("Failed to update snippet", err); + res.status(500).json({ + error: err instanceof Error ? err.message : "Failed to update snippet", + }); + } + }, +); + +// Delete a snippet +// DELETE /snippets/:id +router.delete( + "/:id", + authenticateJWT, + requireDataAccess, + async (req: Request, res: Response) => { + const userId = (req as AuthenticatedRequest).userId; + const { id } = req.params; + + if (!isNonEmptyString(userId) || !id) { + authLogger.warn("Invalid request for snippet delete"); + return res.status(400).json({ error: "Invalid request" }); + } + + try { + const existing = await db + .select() + .from(snippets) + .where(and(eq(snippets.id, parseInt(id)), eq(snippets.userId, userId))); + + if (existing.length === 0) { + return res.status(404).json({ error: "Snippet not found" }); + } + + await db + .delete(snippets) + .where(and(eq(snippets.id, parseInt(id)), eq(snippets.userId, userId))); + + authLogger.success( + `Snippet deleted: ${existing[0].name} by user ${userId}`, + { + operation: "snippet_delete_success", + userId, + snippetId: parseInt(id), + name: existing[0].name, + }, + ); + + res.json({ success: true }); + } catch (err) { + authLogger.error("Failed to delete snippet", err); + res.status(500).json({ + error: err instanceof Error ? err.message : "Failed to delete snippet", + }); + } + }, +); + +export default router; diff --git a/src/backend/database/routes/ssh.ts b/src/backend/database/routes/ssh.ts index cdaf7668..ab8f317d 100644 --- a/src/backend/database/routes/ssh.ts +++ b/src/backend/database/routes/ssh.ts @@ -1,3 +1,4 @@ +import type { AuthenticatedRequest } from "../../../types/index.js"; import express from "express"; import { db } from "../db/index.js"; import { @@ -9,8 +10,7 @@ import { fileManagerShortcuts, } from "../db/schema.js"; import { eq, and, desc, isNotNull, or } from "drizzle-orm"; -import type { Request, Response, NextFunction } from "express"; -import jwt from "jsonwebtoken"; +import type { Request, Response } from "express"; import multer from "multer"; import { sshLogger } from "../../utils/logger.js"; import { SimpleDBOps } from "../../utils/simple-db-ops.js"; @@ -23,11 +23,11 @@ const router = express.Router(); const upload = multer({ storage: multer.memoryStorage() }); -function isNonEmptyString(value: any): value is string { +function isNonEmptyString(value: unknown): value is string { return typeof value === "string" && value.trim().length > 0; } -function isValidPort(port: any): port is number { +function isValidPort(port: unknown): port is number { return typeof port === "number" && port > 0 && port <= 65535; } @@ -75,7 +75,7 @@ router.get("/db/host/internal", async (req: Request, res: Response) => { : []; const hasAutoStartTunnels = tunnelConnections.some( - (tunnel: any) => tunnel.autoStart, + (tunnel: Record) => tunnel.autoStart, ); if (!hasAutoStartTunnels) { @@ -100,7 +100,7 @@ router.get("/db/host/internal", async (req: Request, res: Response) => { credentialId: host.credentialId, enableTunnel: true, tunnelConnections: tunnelConnections.filter( - (tunnel: any) => tunnel.autoStart, + (tunnel: Record) => tunnel.autoStart, ), pin: !!host.pin, enableTerminal: !!host.enableTerminal, @@ -184,8 +184,8 @@ router.post( requireDataAccess, upload.single("key"), async (req: Request, res: Response) => { - const userId = (req as any).userId; - let hostData: any; + const userId = (req as AuthenticatedRequest).userId; + let hostData: Record; if (req.headers["content-type"]?.includes("multipart/form-data")) { if (req.body.data) { @@ -234,6 +234,7 @@ router.post( enableFileManager, defaultPath, tunnelConnections, + statsConfig, } = hostData; if ( !isNonEmptyString(userId) || @@ -251,7 +252,7 @@ router.post( } const effectiveAuthType = authType || authMethod; - const sshDataObj: any = { + const sshDataObj: Record = { userId: userId, name, folder: folder || null, @@ -269,6 +270,7 @@ router.post( : null, enableFileManager: enableFileManager ? 1 : 0, defaultPath: defaultPath || null, + statsConfig: statsConfig ? JSON.stringify(statsConfig) : null, }; if (effectiveAuthType === "password") { @@ -320,9 +322,12 @@ router.post( enableTerminal: !!createdHost.enableTerminal, enableTunnel: !!createdHost.enableTunnel, tunnelConnections: createdHost.tunnelConnections - ? JSON.parse(createdHost.tunnelConnections) + ? JSON.parse(createdHost.tunnelConnections as string) : [], enableFileManager: !!createdHost.enableFileManager, + statsConfig: createdHost.statsConfig + ? JSON.parse(createdHost.statsConfig as string) + : undefined, }; const resolvedHost = (await resolveHostCredentials(baseHost)) || baseHost; @@ -332,7 +337,7 @@ router.post( { operation: "host_create_success", userId, - hostId: createdHost.id, + hostId: createdHost.id as number, name, ip, port, @@ -363,8 +368,8 @@ router.put( upload.single("key"), async (req: Request, res: Response) => { const hostId = req.params.id; - const userId = (req as any).userId; - let hostData: any; + const userId = (req as AuthenticatedRequest).userId; + let hostData: Record; if (req.headers["content-type"]?.includes("multipart/form-data")) { if (req.body.data) { @@ -415,6 +420,7 @@ router.put( enableFileManager, defaultPath, tunnelConnections, + statsConfig, } = hostData; if ( !isNonEmptyString(userId) || @@ -434,7 +440,7 @@ router.put( } const effectiveAuthType = authType || authMethod; - const sshDataObj: any = { + const sshDataObj: Record = { name, folder, tags: Array.isArray(tags) ? tags.join(",") : tags || "", @@ -451,6 +457,7 @@ router.put( : null, enableFileManager: enableFileManager ? 1 : 0, defaultPath: defaultPath || null, + statsConfig: statsConfig ? JSON.stringify(statsConfig) : null, }; if (effectiveAuthType === "password") { @@ -520,9 +527,12 @@ router.put( enableTerminal: !!updatedHost.enableTerminal, enableTunnel: !!updatedHost.enableTunnel, tunnelConnections: updatedHost.tunnelConnections - ? JSON.parse(updatedHost.tunnelConnections) + ? JSON.parse(updatedHost.tunnelConnections as string) : [], enableFileManager: !!updatedHost.enableFileManager, + statsConfig: updatedHost.statsConfig + ? JSON.parse(updatedHost.statsConfig as string) + : undefined, }; const resolvedHost = (await resolveHostCredentials(baseHost)) || baseHost; @@ -559,7 +569,7 @@ router.put( // Route: Get SSH data for the authenticated user (requires JWT) // GET /ssh/host router.get("/db/host", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!isNonEmptyString(userId)) { sshLogger.warn("Invalid userId for SSH data fetch", { operation: "host_fetch", @@ -575,7 +585,7 @@ router.get("/db/host", authenticateJWT, async (req: Request, res: Response) => { ); const result = await Promise.all( - data.map(async (row: any) => { + data.map(async (row: Record) => { const baseHost = { ...row, tags: @@ -588,9 +598,12 @@ router.get("/db/host", authenticateJWT, async (req: Request, res: Response) => { enableTerminal: !!row.enableTerminal, enableTunnel: !!row.enableTunnel, tunnelConnections: row.tunnelConnections - ? JSON.parse(row.tunnelConnections) + ? JSON.parse(row.tunnelConnections as string) : [], enableFileManager: !!row.enableFileManager, + statsConfig: row.statsConfig + ? JSON.parse(row.statsConfig as string) + : undefined, }; return (await resolveHostCredentials(baseHost)) || baseHost; @@ -614,7 +627,7 @@ router.get( authenticateJWT, async (req: Request, res: Response) => { const hostId = req.params.id; - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!isNonEmptyString(userId) || !hostId) { sshLogger.warn("Invalid userId or hostId for SSH host fetch by ID", { @@ -655,6 +668,9 @@ router.get( ? JSON.parse(host.tunnelConnections) : [], enableFileManager: !!host.enableFileManager, + statsConfig: host.statsConfig + ? JSON.parse(host.statsConfig) + : undefined, }; res.json((await resolveHostCredentials(result)) || result); @@ -677,7 +693,7 @@ router.get( requireDataAccess, async (req: Request, res: Response) => { const hostId = req.params.id; - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!isNonEmptyString(userId) || !hostId) { return res.status(400).json({ error: "Invalid userId or hostId" }); @@ -711,7 +727,7 @@ router.get( authType: resolvedHost.authType, password: resolvedHost.password || null, key: resolvedHost.key || null, - keyPassword: resolvedHost.keyPassword || null, + keyPassword: resolvedHost.key_password || null, keyType: resolvedHost.keyType || null, folder: resolvedHost.folder, tags: @@ -724,7 +740,7 @@ router.get( enableFileManager: !!resolvedHost.enableFileManager, defaultPath: resolvedHost.defaultPath, tunnelConnections: resolvedHost.tunnelConnections - ? JSON.parse(resolvedHost.tunnelConnections) + ? JSON.parse(resolvedHost.tunnelConnections as string) : [], }; @@ -752,7 +768,7 @@ router.delete( "/db/host/:id", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const hostId = req.params.id; if (!isNonEmptyString(userId) || !hostId) { @@ -816,7 +832,7 @@ router.delete( ), ); - const result = await db + await db .delete(sshData) .where(and(eq(sshData.id, numericHostId), eq(sshData.userId, userId))); @@ -851,7 +867,7 @@ router.get( "/file_manager/recent", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const hostId = req.query.hostId ? parseInt(req.query.hostId as string) : null; @@ -893,7 +909,7 @@ router.post( "/file_manager/recent", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { hostId, path, name } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { @@ -942,8 +958,8 @@ router.delete( "/file_manager/recent", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; - const { hostId, path, name } = req.body; + const userId = (req as AuthenticatedRequest).userId; + const { hostId, path } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { sshLogger.warn("Invalid data for recent file deletion"); @@ -975,7 +991,7 @@ router.get( "/file_manager/pinned", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const hostId = req.query.hostId ? parseInt(req.query.hostId as string) : null; @@ -1016,7 +1032,7 @@ router.post( "/file_manager/pinned", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { hostId, path, name } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { @@ -1062,8 +1078,8 @@ router.delete( "/file_manager/pinned", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; - const { hostId, path, name } = req.body; + const userId = (req as AuthenticatedRequest).userId; + const { hostId, path } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { sshLogger.warn("Invalid data for pinned file deletion"); @@ -1095,7 +1111,7 @@ router.get( "/file_manager/shortcuts", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const hostId = req.query.hostId ? parseInt(req.query.hostId as string) : null; @@ -1136,7 +1152,7 @@ router.post( "/file_manager/shortcuts", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { hostId, path, name } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { @@ -1182,8 +1198,8 @@ router.delete( "/file_manager/shortcuts", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; - const { hostId, path, name } = req.body; + const userId = (req as AuthenticatedRequest).userId; + const { hostId, path } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { sshLogger.warn("Invalid data for shortcut deletion"); @@ -1209,21 +1225,26 @@ router.delete( }, ); -async function resolveHostCredentials(host: any): Promise { +async function resolveHostCredentials( + host: Record, +): Promise> { try { if (host.credentialId && host.userId) { + const credentialId = host.credentialId as number; + const userId = host.userId as string; + const credentials = await SimpleDBOps.select( db .select() .from(sshCredentials) .where( and( - eq(sshCredentials.id, host.credentialId), - eq(sshCredentials.userId, host.userId), + eq(sshCredentials.id, credentialId), + eq(sshCredentials.userId, userId), ), ), "ssh_credentials", - host.userId, + userId, ); if (credentials.length > 0) { @@ -1239,6 +1260,7 @@ async function resolveHostCredentials(host: any): Promise { }; } } + const result = { ...host }; if (host.key_password !== undefined) { if (result.keyPassword === undefined) { @@ -1261,7 +1283,7 @@ router.put( "/folders/rename", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { oldName, newName } = req.body; if (!isNonEmptyString(userId) || !oldName || !newName) { @@ -1326,7 +1348,7 @@ router.post( "/bulk-import", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { hosts } = req.body; if (!Array.isArray(hosts) || hosts.length === 0) { @@ -1398,7 +1420,7 @@ router.post( continue; } - const sshDataObj: any = { + const sshDataObj: Record = { userId: userId, name: hostData.name || `${hostData.username}@${hostData.ip}`, folder: hostData.folder || "Default", @@ -1411,7 +1433,7 @@ router.post( credentialId: hostData.authType === "credential" ? hostData.credentialId : null, key: hostData.authType === "key" ? hostData.key : null, - key_password: + keyPassword: hostData.authType === "key" ? hostData.keyPassword || hostData.key_password || null : null, @@ -1425,6 +1447,9 @@ router.post( tunnelConnections: hostData.tunnelConnections ? JSON.stringify(hostData.tunnelConnections) : "[]", + statsConfig: hostData.statsConfig + ? JSON.stringify(hostData.statsConfig) + : null, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; @@ -1455,7 +1480,7 @@ router.post( authenticateJWT, requireDataAccess, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { sshConfigId } = req.body; if (!sshConfigId || typeof sshConfigId !== "number") { @@ -1519,7 +1544,7 @@ router.post( const tunnelConnections = JSON.parse(config.tunnelConnections); const resolvedConnections = await Promise.all( - tunnelConnections.map(async (tunnel: any) => { + tunnelConnections.map(async (tunnel: Record) => { if ( tunnel.autoStart && tunnel.endpointHost && @@ -1567,7 +1592,7 @@ router.post( } } - const updateResult = await db + await db .update(sshData) .set({ autostartPassword: decryptedConfig.password || null, @@ -1608,7 +1633,7 @@ router.delete( "/autostart/disable", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { sshConfigId } = req.body; if (!sshConfigId || typeof sshConfigId !== "number") { @@ -1624,7 +1649,7 @@ router.delete( } try { - const result = await db + await db .update(sshData) .set({ autostartPassword: null, @@ -1654,7 +1679,7 @@ router.get( "/autostart/status", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const autostartConfigs = await db diff --git a/src/backend/database/routes/users.ts b/src/backend/database/routes/users.ts index 91f761e2..ee739279 100644 --- a/src/backend/database/routes/users.ts +++ b/src/backend/database/routes/users.ts @@ -1,3 +1,4 @@ +import type { AuthenticatedRequest } from "../../../types/index.js"; import express from "express"; import crypto from "crypto"; import { db } from "../db/index.js"; @@ -27,48 +28,48 @@ async function verifyOIDCToken( idToken: string, issuerUrl: string, clientId: string, -): Promise { +): Promise> { + const normalizedIssuerUrl = issuerUrl.endsWith("/") + ? issuerUrl.slice(0, -1) + : issuerUrl; + const possibleIssuers = [ + issuerUrl, + normalizedIssuerUrl, + issuerUrl.replace(/\/application\/o\/[^/]+$/, ""), + normalizedIssuerUrl.replace(/\/application\/o\/[^/]+$/, ""), + ]; + + const jwksUrls = [ + `${normalizedIssuerUrl}/.well-known/jwks.json`, + `${normalizedIssuerUrl}/jwks/`, + `${normalizedIssuerUrl.replace(/\/application\/o\/[^/]+$/, "")}/.well-known/jwks.json`, + ]; + try { - const normalizedIssuerUrl = issuerUrl.endsWith("/") - ? issuerUrl.slice(0, -1) - : issuerUrl; - const possibleIssuers = [ - issuerUrl, - normalizedIssuerUrl, - issuerUrl.replace(/\/application\/o\/[^\/]+$/, ""), - normalizedIssuerUrl.replace(/\/application\/o\/[^\/]+$/, ""), - ]; - - const jwksUrls = [ - `${normalizedIssuerUrl}/.well-known/jwks.json`, - `${normalizedIssuerUrl}/jwks/`, - `${normalizedIssuerUrl.replace(/\/application\/o\/[^\/]+$/, "")}/.well-known/jwks.json`, - ]; - - try { - const discoveryUrl = `${normalizedIssuerUrl}/.well-known/openid-configuration`; - const discoveryResponse = await fetch(discoveryUrl); - if (discoveryResponse.ok) { - const discovery = (await discoveryResponse.json()) as any; - if (discovery.jwks_uri) { - jwksUrls.unshift(discovery.jwks_uri); - } + const discoveryUrl = `${normalizedIssuerUrl}/.well-known/openid-configuration`; + const discoveryResponse = await fetch(discoveryUrl); + if (discoveryResponse.ok) { + const discovery = (await discoveryResponse.json()) as Record< + string, + unknown + >; + if (discovery.jwks_uri) { + jwksUrls.unshift(discovery.jwks_uri as string); } - } catch (discoveryError) { - authLogger.error(`OIDC discovery failed: ${discoveryError}`); } + } catch (discoveryError) { + authLogger.error(`OIDC discovery failed: ${discoveryError}`); + } - let jwks: any = null; - let jwksUrl: string | null = null; + let jwks: Record | null = null; for (const url of jwksUrls) { try { const response = await fetch(url); if (response.ok) { - const jwksData = (await response.json()) as any; + const jwksData = (await response.json()) as Record;; if (jwksData && jwksData.keys && Array.isArray(jwksData.keys)) { jwks = jwksData; - jwksUrl = url; break; } else { authLogger.error( @@ -77,62 +78,54 @@ async function verifyOIDCToken( } } else { } - } catch (error) { + } catch { continue; } } - if (!jwks) { - throw new Error("Failed to fetch JWKS from any URL"); - } - - if (!jwks.keys || !Array.isArray(jwks.keys)) { - throw new Error( - `Invalid JWKS response structure. Expected 'keys' array, got: ${JSON.stringify(jwks)}`, - ); - } - - const header = JSON.parse( - Buffer.from(idToken.split(".")[0], "base64").toString(), - ); - const keyId = header.kid; - - const publicKey = jwks.keys.find((key: any) => key.kid === keyId); - if (!publicKey) { - throw new Error( - `No matching public key found for key ID: ${keyId}. Available keys: ${jwks.keys.map((k: any) => k.kid).join(", ")}`, - ); - } - - const { importJWK, jwtVerify } = await import("jose"); - const key = await importJWK(publicKey); - - const { payload } = await jwtVerify(idToken, key, { - issuer: possibleIssuers, - audience: clientId, - }); - - return payload; - } catch (error) { - throw error; + if (!jwks) { + throw new Error("Failed to fetch JWKS from any URL"); } + + if (!jwks.keys || !Array.isArray(jwks.keys)) { + throw new Error( + `Invalid JWKS response structure. Expected 'keys' array, got: ${JSON.stringify(jwks)}`, + ); + } + + const header = JSON.parse( + Buffer.from(idToken.split(".")[0], "base64").toString(), + ); + const keyId = header.kid; + + const publicKey = jwks.keys.find( + (key: Record) => key.kid === keyId, + ); + if (!publicKey) { + throw new Error( + `No matching public key found for key ID: ${keyId}. Available keys: ${jwks.keys.map((k: Record) => k.kid).join(", ")}`, + ); + } + + const { importJWK, jwtVerify } = await import("jose"); + const key = await importJWK(publicKey); + + const { payload } = await jwtVerify(idToken, key, { + issuer: possibleIssuers, + audience: clientId, + }); + + return payload; } const router = express.Router(); -function isNonEmptyString(val: any): val is string { +function isNonEmptyString(val: unknown): val is string { return typeof val === "string" && val.trim().length > 0; } -interface JWTPayload { - userId: string; - iat?: number; - exp?: number; -} - const authenticateJWT = authManager.createAuthMiddleware(); const requireAdmin = authManager.createAdminMiddleware(); -const requireDataAccess = authManager.createDataAccessMiddleware(); // Route: Create traditional user (username/password) // POST /users/create @@ -141,7 +134,7 @@ router.post("/create", async (req, res) => { const row = db.$client .prepare("SELECT value FROM settings WHERE key = 'allow_registration'") .get(); - if (row && (row as any).value !== "true") { + if (row && (row as Record).value !== "true") { return res .status(403) .json({ error: "Registration is currently disabled" }); @@ -186,7 +179,7 @@ router.post("/create", async (req, res) => { const countResult = db.$client .prepare("SELECT COUNT(*) as count FROM users") .get(); - isFirstUser = ((countResult as any)?.count || 0) === 0; + isFirstUser = ((countResult as { count?: number })?.count || 0) === 0; const saltRounds = parseInt(process.env.SALT || "10", 10); const password_hash = await bcrypt.hash(password, saltRounds); @@ -250,7 +243,7 @@ router.post("/create", async (req, res) => { // Route: Create OIDC provider configuration (admin only) // POST /users/oidc-config router.post("/oidc-config", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const user = await db.select().from(users).where(eq(users.id, userId)); if (!user || user.length === 0 || !user[0].is_admin) { @@ -390,7 +383,7 @@ router.post("/oidc-config", authenticateJWT, async (req, res) => { // Route: Disable OIDC configuration (admin only) // DELETE /users/oidc-config router.delete("/oidc-config", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const user = await db.select().from(users).where(eq(users.id, userId)); if (!user || user.length === 0 || !user[0].is_admin) { @@ -420,7 +413,7 @@ router.get("/oidc-config", async (req, res) => { return res.json(null); } - let config = JSON.parse((row as any).value); + let config = JSON.parse((row as Record).value as string); if (config.client_secret) { if (config.client_secret.startsWith("encrypted:")) { @@ -450,7 +443,7 @@ router.get("/oidc-config", async (req, res) => { } else { config.client_secret = "[ENCRYPTED - PASSWORD REQUIRED]"; } - } catch (decryptError) { + } catch { authLogger.warn("Failed to decrypt OIDC config for admin", { operation: "oidc_config_decrypt_failed", userId, @@ -497,13 +490,13 @@ router.get("/oidc/authorize", async (req, res) => { return res.status(404).json({ error: "OIDC not configured" }); } - const config = JSON.parse((row as any).value); + const config = JSON.parse((row as Record).value as string); const state = nanoid(); const nonce = nanoid(); let origin = req.get("Origin") || - req.get("Referer")?.replace(/\/[^\/]*$/, "") || + req.get("Referer")?.replace(/\/[^/]*$/, "") || "http://localhost:5173"; if (origin.includes("localhost")) { @@ -552,7 +545,8 @@ router.get("/oidc/callback", async (req, res) => { .status(400) .json({ error: "Invalid state parameter - redirect URI not found" }); } - const redirectUri = (storedRedirectRow as any).value; + const redirectUri = (storedRedirectRow as Record) + .value as string; try { const storedNonce = db.$client @@ -576,7 +570,9 @@ router.get("/oidc/callback", async (req, res) => { return res.status(500).json({ error: "OIDC not configured" }); } - const config = JSON.parse((configRow as any).value); + const config = JSON.parse( + (configRow as Record).value as string, + ); const tokenResponse = await fetch(config.token_url, { method: "POST", @@ -602,26 +598,26 @@ router.get("/oidc/callback", async (req, res) => { .json({ error: "Failed to exchange authorization code" }); } - const tokenData = (await tokenResponse.json()) as any; + const tokenData = (await tokenResponse.json()) as Record; - let userInfo: any = null; - let userInfoUrls: string[] = []; + let userInfo: Record = null; + const userInfoUrls: string[] = []; const normalizedIssuerUrl = config.issuer_url.endsWith("/") ? config.issuer_url.slice(0, -1) : config.issuer_url; - const baseUrl = normalizedIssuerUrl.replace( - /\/application\/o\/[^\/]+$/, - "", - ); + const baseUrl = normalizedIssuerUrl.replace(/\/application\/o\/[^/]+$/, ""); try { const discoveryUrl = `${normalizedIssuerUrl}/.well-known/openid-configuration`; const discoveryResponse = await fetch(discoveryUrl); if (discoveryResponse.ok) { - const discovery = (await discoveryResponse.json()) as any; + const discovery = (await discoveryResponse.json()) as Record< + string, + unknown + >; if (discovery.userinfo_endpoint) { - userInfoUrls.push(discovery.userinfo_endpoint); + userInfoUrls.push(discovery.userinfo_endpoint as string); } } } catch (discoveryError) { @@ -646,13 +642,14 @@ router.get("/oidc/callback", async (req, res) => { if (tokenData.id_token) { try { userInfo = await verifyOIDCToken( - tokenData.id_token, + tokenData.id_token as string, config.issuer_url, config.client_id, ); - } catch (error) { + } catch { + // Fallback to manual decoding try { - const parts = tokenData.id_token.split("."); + const parts = (tokenData.id_token as string).split("."); if (parts.length === 3) { const payload = JSON.parse( Buffer.from(parts[1], "base64").toString(), @@ -675,7 +672,10 @@ router.get("/oidc/callback", async (req, res) => { }); if (userInfoResponse.ok) { - userInfo = await userInfoResponse.json(); + userInfo = (await userInfoResponse.json()) as Record< + string, + unknown + >; break; } else { authLogger.error( @@ -698,24 +698,25 @@ router.get("/oidc/callback", async (req, res) => { return res.status(400).json({ error: "Failed to get user information" }); } - const getNestedValue = (obj: any, path: string): any => { + const getNestedValue = ( + obj: Record, + path: string, + ): unknown => { if (!path || !obj) return null; return path.split(".").reduce((current, key) => current?.[key], obj); }; - const identifier = - getNestedValue(userInfo, config.identifier_path) || + const identifier = (getNestedValue(userInfo, config.identifier_path) || userInfo[config.identifier_path] || userInfo.sub || userInfo.email || - userInfo.preferred_username; + userInfo.preferred_username) as string; - const name = - getNestedValue(userInfo, config.name_path) || + const name = (getNestedValue(userInfo, config.name_path) || userInfo[config.name_path] || userInfo.name || userInfo.given_name || - identifier; + identifier) as string; if (!identifier) { authLogger.error( @@ -739,7 +740,7 @@ router.get("/oidc/callback", async (req, res) => { const countResult = db.$client .prepare("SELECT COUNT(*) as count FROM users") .get(); - isFirstUser = ((countResult as any)?.count || 0) === 0; + isFirstUser = ((countResult as { count?: number })?.count || 0) === 0; const id = nanoid(); await db.insert(users).values({ @@ -749,14 +750,14 @@ router.get("/oidc/callback", async (req, res) => { is_admin: isFirstUser, is_oidc: true, oidc_identifier: identifier, - client_id: config.client_id, - client_secret: config.client_secret, - issuer_url: config.issuer_url, - authorization_url: config.authorization_url, - token_url: config.token_url, - identifier_path: config.identifier_path, - name_path: config.name_path, - scopes: config.scopes, + client_id: String(config.client_id), + client_secret: String(config.client_secret), + issuer_url: String(config.issuer_url), + authorization_url: String(config.authorization_url), + token_url: String(config.token_url), + identifier_path: String(config.identifier_path), + name_path: String(config.name_path), + scopes: String(config.scopes), }); try { @@ -801,7 +802,10 @@ router.get("/oidc/callback", async (req, res) => { expiresIn: "50d", }); - let frontendUrl = redirectUri.replace("/users/oidc/callback", ""); + let frontendUrl = (redirectUri as string).replace( + "/users/oidc/callback", + "", + ); if (frontendUrl.includes("localhost")) { frontendUrl = "http://localhost:5173"; @@ -820,7 +824,10 @@ router.get("/oidc/callback", async (req, res) => { } catch (err) { authLogger.error("OIDC callback failed", err); - let frontendUrl = redirectUri.replace("/users/oidc/callback", ""); + let frontendUrl = (redirectUri as string).replace( + "/users/oidc/callback", + "", + ); if (frontendUrl.includes("localhost")) { frontendUrl = "http://localhost:5173"; @@ -847,6 +854,23 @@ router.post("/login", async (req, res) => { return res.status(400).json({ error: "Invalid username or password" }); } + try { + const row = db.$client + .prepare("SELECT value FROM settings WHERE key = 'allow_password_login'") + .get(); + if (row && (row as { value: string }).value !== "true") { + return res + .status(403) + .json({ error: "Password authentication is currently disabled" }); + } + } catch (e) { + authLogger.error("Failed to check password login status", { + operation: "login_check", + error: e, + }); + return res.status(500).json({ error: "Failed to check login status" }); + } + try { const user = await db .select() @@ -893,7 +917,8 @@ router.post("/login", async (req, res) => { if (kekSalt.length === 0) { await authManager.registerUser(userRecord.id, password); } - } catch (setupError) {} + } catch { + } const dataUnlocked = await authManager.authenticateUser( userRecord.id, @@ -926,7 +951,7 @@ router.post("/login", async (req, res) => { dataUnlocked: true, }); - const response: any = { + const response: Record = { success: true, is_admin: !!userRecord.is_admin, username: userRecord.username, @@ -957,7 +982,7 @@ router.post("/login", async (req, res) => { // POST /users/logout router.post("/logout", async (req, res) => { try { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (userId) { authManager.logoutUser(userId); @@ -979,7 +1004,7 @@ router.post("/logout", async (req, res) => { // Route: Get current user's info using JWT // GET /users/me router.get("/me", authenticateJWT, async (req: Request, res: Response) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!isNonEmptyString(userId)) { authLogger.warn("Invalid userId in JWT for /users/me"); return res.status(401).json({ error: "Invalid userId" }); @@ -1014,7 +1039,7 @@ router.get("/setup-required", async (req, res) => { const countResult = db.$client .prepare("SELECT COUNT(*) as count FROM users") .get(); - const count = (countResult as any)?.count || 0; + const count = (countResult as { count?: number })?.count || 0; res.json({ setup_required: count === 0, @@ -1028,7 +1053,7 @@ router.get("/setup-required", async (req, res) => { // Route: Count users (admin only - for dashboard statistics) // GET /users/count router.get("/count", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const user = await db.select().from(users).where(eq(users.id, userId)); if (!user[0] || !user[0].is_admin) { @@ -1038,7 +1063,7 @@ router.get("/count", authenticateJWT, async (req, res) => { const countResult = db.$client .prepare("SELECT COUNT(*) as count FROM users") .get(); - const count = (countResult as any)?.count || 0; + const count = (countResult as { count?: number })?.count || 0; res.json({ count }); } catch (err) { authLogger.error("Failed to count users", err); @@ -1065,7 +1090,9 @@ router.get("/registration-allowed", async (req, res) => { const row = db.$client .prepare("SELECT value FROM settings WHERE key = 'allow_registration'") .get(); - res.json({ allowed: row ? (row as any).value === "true" : true }); + res.json({ + allowed: row ? (row as Record).value === "true" : true, + }); } catch (err) { authLogger.error("Failed to get registration allowed", err); res.status(500).json({ error: "Failed to get registration allowed" }); @@ -1075,7 +1102,7 @@ router.get("/registration-allowed", async (req, res) => { // Route: Set registration allowed status (admin only) // PATCH /users/registration-allowed router.patch("/registration-allowed", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const user = await db.select().from(users).where(eq(users.id, userId)); if (!user || user.length === 0 || !user[0].is_admin) { @@ -1095,10 +1122,51 @@ router.patch("/registration-allowed", authenticateJWT, async (req, res) => { } }); +// Route: Get password login allowed status (public - needed for login page) +// GET /users/password-login-allowed +router.get("/password-login-allowed", async (req, res) => { + try { + const row = db.$client + .prepare("SELECT value FROM settings WHERE key = 'allow_password_login'") + .get(); + res.json({ + allowed: row ? (row as { value: string }).value === "true" : true, + }); + } catch (err) { + authLogger.error("Failed to get password login allowed", err); + res.status(500).json({ error: "Failed to get password login allowed" }); + } +}); + +// Route: Set password login allowed status (admin only) +// PATCH /users/password-login-allowed +router.patch("/password-login-allowed", authenticateJWT, async (req, res) => { + const userId = (req as AuthenticatedRequest).userId; + try { + const user = await db.select().from(users).where(eq(users.id, userId)); + if (!user || user.length === 0 || !user[0].is_admin) { + return res.status(403).json({ error: "Not authorized" }); + } + const { allowed } = req.body; + if (typeof allowed !== "boolean") { + return res.status(400).json({ error: "Invalid value for allowed" }); + } + db.$client + .prepare( + "UPDATE settings SET value = ? WHERE key = 'allow_password_login'", + ) + .run(allowed ? "true" : "false"); + res.json({ allowed }); + } catch (err) { + authLogger.error("Failed to set password login allowed", err); + res.status(500).json({ error: "Failed to set password login allowed" }); + } +}); + // Route: Delete user account // DELETE /users/delete-account router.delete("/delete-account", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { password } = req.body; if (!isNonEmptyString(password)) { @@ -1134,7 +1202,7 @@ router.delete("/delete-account", authenticateJWT, async (req, res) => { const adminCount = db.$client .prepare("SELECT COUNT(*) as count FROM users WHERE is_admin = 1") .get(); - if ((adminCount as any)?.count <= 1) { + if (((adminCount as { count?: number })?.count || 0) <= 1) { return res .status(403) .json({ error: "Cannot delete the last admin user" }); @@ -1224,7 +1292,9 @@ router.post("/verify-reset-code", async (req, res) => { .json({ error: "No reset code found for this user" }); } - const resetData = JSON.parse((resetDataRow as any).value); + const resetData = JSON.parse( + (resetDataRow as Record).value as string, + ); const now = new Date(); const expiresAt = new Date(resetData.expiresAt); @@ -1282,7 +1352,9 @@ router.post("/complete-reset", async (req, res) => { return res.status(400).json({ error: "No temporary token found" }); } - const tempTokenData = JSON.parse((tempTokenRow as any).value); + const tempTokenData = JSON.parse( + (tempTokenRow as Record).value as string, + ); const now = new Date(); const expiresAt = new Date(tempTokenData.expiresAt); @@ -1315,48 +1387,8 @@ router.post("/complete-reset", async (req, res) => { .where(eq(users.username, username)); try { - const hasActiveSession = authManager.isUserUnlocked(userId); - - if (hasActiveSession) { - const success = await authManager.resetUserPasswordWithPreservedDEK( - userId, - newPassword, - ); - - if (!success) { - authLogger.warn( - `Failed to preserve DEK during password reset for ${username}. Creating new DEK - data will be lost.`, - { - operation: "password_reset_preserve_failed", - userId, - username, - }, - ); - await authManager.registerUser(userId, newPassword); - authManager.logoutUser(userId); - } else { - authLogger.success( - `Password reset completed for user: ${username}. Data preserved using existing session.`, - { - operation: "password_reset_data_preserved", - userId, - username, - }, - ); - } - } else { - await authManager.registerUser(userId, newPassword); - authManager.logoutUser(userId); - - authLogger.warn( - `Password reset completed for user: ${username}. Existing encrypted data is now inaccessible and will need to be re-entered.`, - { - operation: "password_reset_data_inaccessible", - userId, - username, - }, - ); - } + await authManager.registerUser(userId, newPassword); + authManager.logoutUser(userId); await db .update(users) @@ -1366,6 +1398,15 @@ router.post("/complete-reset", async (req, res) => { totp_backup_codes: null, }) .where(eq(users.id, userId)); + + authLogger.warn( + `Password reset completed for user: ${username}. Existing encrypted data is now inaccessible and will need to be re-entered.`, + { + operation: "password_reset_data_inaccessible", + userId, + username, + }, + ); } catch (encryptionError) { authLogger.error( "Failed to re-encrypt user data after password reset", @@ -1382,6 +1423,8 @@ router.post("/complete-reset", async (req, res) => { }); } + authLogger.success(`Password successfully reset for user: ${username}`); + db.$client .prepare("DELETE FROM settings WHERE key = ?") .run(`reset_code_${username}`); @@ -1399,7 +1442,7 @@ router.post("/complete-reset", async (req, res) => { // Route: List all users (admin only) // GET /users/list router.get("/list", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const user = await db.select().from(users).where(eq(users.id, userId)); if (!user || user.length === 0 || !user[0].is_admin) { @@ -1425,7 +1468,7 @@ router.get("/list", authenticateJWT, async (req, res) => { // Route: Make user admin (admin only) // POST /users/make-admin router.post("/make-admin", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { username } = req.body; if (!isNonEmptyString(username)) { @@ -1468,7 +1511,7 @@ router.post("/make-admin", authenticateJWT, async (req, res) => { // Route: Remove admin status (admin only) // POST /users/remove-admin router.post("/remove-admin", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { username } = req.body; if (!isNonEmptyString(username)) { @@ -1587,7 +1630,7 @@ router.post("/totp/verify-login", async (req, res) => { backupCodes = userRecord.totp_backup_codes ? JSON.parse(userRecord.totp_backup_codes) : []; - } catch (parseError) { + } catch { backupCodes = []; } @@ -1625,7 +1668,7 @@ router.post("/totp/verify-login", async (req, res) => { }); } - const response: any = { + const response: Record = { success: true, is_admin: !!userRecord.is_admin, username: userRecord.username, @@ -1655,7 +1698,7 @@ router.post("/totp/verify-login", async (req, res) => { // Route: Setup TOTP // POST /users/totp/setup router.post("/totp/setup", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const user = await db.select().from(users).where(eq(users.id, userId)); @@ -1694,7 +1737,7 @@ router.post("/totp/setup", authenticateJWT, async (req, res) => { // Route: Enable TOTP // POST /users/totp/enable router.post("/totp/enable", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { totp_code } = req.body; if (!totp_code) { @@ -1753,7 +1796,7 @@ router.post("/totp/enable", authenticateJWT, async (req, res) => { // Route: Disable TOTP // POST /users/totp/disable router.post("/totp/disable", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { password, totp_code } = req.body; if (!password && !totp_code) { @@ -1811,7 +1854,7 @@ router.post("/totp/disable", authenticateJWT, async (req, res) => { // Route: Generate new backup codes // POST /users/totp/backup-codes router.post("/totp/backup-codes", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { password, totp_code } = req.body; if (!password && !totp_code) { @@ -1869,7 +1912,7 @@ router.post("/totp/backup-codes", authenticateJWT, async (req, res) => { // Route: Delete user (admin only) // DELETE /users/delete-user router.delete("/delete-user", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { username } = req.body; if (!isNonEmptyString(username)) { @@ -1898,7 +1941,7 @@ router.delete("/delete-user", authenticateJWT, async (req, res) => { const adminCount = db.$client .prepare("SELECT COUNT(*) as count FROM users WHERE is_admin = 1") .get(); - if ((adminCount as any)?.count <= 1) { + if (((adminCount as { count?: number })?.count || 0) <= 1) { return res .status(403) .json({ error: "Cannot delete the last admin user" }); @@ -1955,7 +1998,7 @@ router.delete("/delete-user", authenticateJWT, async (req, res) => { // Route: User data unlock - used when session expires // POST /users/unlock-data router.post("/unlock-data", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { password } = req.body; if (!password) { @@ -1988,7 +2031,7 @@ router.post("/unlock-data", authenticateJWT, async (req, res) => { // Route: Check user data unlock status // GET /users/data-status router.get("/data-status", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; try { const isUnlocked = authManager.isUserUnlocked(userId); @@ -2010,7 +2053,7 @@ router.get("/data-status", authenticateJWT, async (req, res) => { // Route: Change user password (re-encrypt data keys) // POST /users/change-password router.post("/change-password", authenticateJWT, async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; const { currentPassword, newPassword } = req.body; if (!currentPassword || !newPassword) { diff --git a/src/backend/homepage.ts b/src/backend/homepage.ts new file mode 100644 index 00000000..82e1c95d --- /dev/null +++ b/src/backend/homepage.ts @@ -0,0 +1,261 @@ +import express from "express"; +import cors from "cors"; +import cookieParser from "cookie-parser"; +import { getDb } from "./database/db/index.js"; +import { recentActivity, sshData } from "./database/db/schema.js"; +import { eq, and, desc } from "drizzle-orm"; +import { homepageLogger } from "./utils/logger.js"; +import { SimpleDBOps } from "./utils/simple-db-ops.js"; +import { AuthManager } from "./utils/auth-manager.js"; +import type { AuthenticatedRequest } from "../types/index.js"; + +const app = express(); +const authManager = AuthManager.getInstance(); + +// Track server start time +const serverStartTime = Date.now(); + +app.use( + cors({ + origin: (origin, callback) => { + if (!origin) return callback(null, true); + + const allowedOrigins = [ + "http://localhost:5173", + "http://localhost:3000", + "http://127.0.0.1:5173", + "http://127.0.0.1:3000", + ]; + + if (origin.startsWith("https://")) { + return callback(null, true); + } + + if (origin.startsWith("http://")) { + return callback(null, true); + } + + if (allowedOrigins.includes(origin)) { + return callback(null, true); + } + + callback(new Error("Not allowed by CORS")); + }, + credentials: true, + methods: ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"], + allowedHeaders: [ + "Content-Type", + "Authorization", + "User-Agent", + "X-Electron-App", + ], + }), +); +app.use(cookieParser()); +app.use(express.json({ limit: "1mb" })); + +app.use(authManager.createAuthMiddleware()); + +// Get server uptime +app.get("/uptime", async (req, res) => { + try { + const uptimeMs = Date.now() - serverStartTime; + const uptimeSeconds = Math.floor(uptimeMs / 1000); + const days = Math.floor(uptimeSeconds / 86400); + const hours = Math.floor((uptimeSeconds % 86400) / 3600); + const minutes = Math.floor((uptimeSeconds % 3600) / 60); + + res.json({ + uptimeMs, + uptimeSeconds, + formatted: `${days}d ${hours}h ${minutes}m`, + }); + } catch (err) { + homepageLogger.error("Failed to get uptime", err); + res.status(500).json({ error: "Failed to get uptime" }); + } +}); + +// Get recent activity for current user +app.get("/activity/recent", async (req, res) => { + try { + const userId = (req as AuthenticatedRequest).userId; + + if (!SimpleDBOps.isUserDataUnlocked(userId)) { + return res.status(401).json({ + error: "Session expired - please log in again", + code: "SESSION_EXPIRED", + }); + } + + const limit = Number(req.query.limit) || 20; + + const activities = await SimpleDBOps.select( + getDb() + .select() + .from(recentActivity) + .where(eq(recentActivity.userId, userId)) + .orderBy(desc(recentActivity.timestamp)) + .limit(limit), + "recent_activity", + userId, + ); + + res.json(activities); + } catch (err) { + homepageLogger.error("Failed to get recent activity", err); + res.status(500).json({ error: "Failed to get recent activity" }); + } +}); + +// Log new activity +app.post("/activity/log", async (req, res) => { + try { + const userId = (req as AuthenticatedRequest).userId; + + if (!SimpleDBOps.isUserDataUnlocked(userId)) { + return res.status(401).json({ + error: "Session expired - please log in again", + code: "SESSION_EXPIRED", + }); + } + + const { type, hostId, hostName } = req.body; + + if (!type || !hostId || !hostName) { + return res.status(400).json({ + error: "Missing required fields: type, hostId, hostName", + }); + } + + if (type !== "terminal" && type !== "file_manager") { + return res.status(400).json({ + error: "Invalid activity type. Must be 'terminal' or 'file_manager'", + }); + } + + // Verify the host belongs to the user + const hosts = await SimpleDBOps.select( + getDb() + .select() + .from(sshData) + .where(and(eq(sshData.id, hostId), eq(sshData.userId, userId))), + "ssh_data", + userId, + ); + + if (hosts.length === 0) { + return res.status(404).json({ error: "Host not found" }); + } + + // Check if this activity already exists in recent history (within last 5 minutes) + const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000).toISOString(); + const recentSimilar = await SimpleDBOps.select( + getDb() + .select() + .from(recentActivity) + .where( + and( + eq(recentActivity.userId, userId), + eq(recentActivity.hostId, hostId), + eq(recentActivity.type, type), + ), + ) + .orderBy(desc(recentActivity.timestamp)) + .limit(1), + "recent_activity", + userId, + ); + + if ( + recentSimilar.length > 0 && + recentSimilar[0].timestamp >= fiveMinutesAgo + ) { + // Activity already logged recently, don't duplicate + return res.json({ + message: "Activity already logged recently", + id: recentSimilar[0].id, + }); + } + + // Insert new activity + const result = (await SimpleDBOps.insert( + recentActivity, + "recent_activity", + { + userId, + type, + hostId, + hostName, + }, + userId, + )) as unknown as { id: number }; + + // Keep only the last 100 activities per user to prevent bloat + const allActivities = await SimpleDBOps.select( + getDb() + .select() + .from(recentActivity) + .where(eq(recentActivity.userId, userId)) + .orderBy(desc(recentActivity.timestamp)), + "recent_activity", + userId, + ); + + if (allActivities.length > 100) { + const toDelete = allActivities.slice(100); + for (const activity of toDelete) { + await SimpleDBOps.delete(recentActivity, "recent_activity", userId); + } + } + + res.json({ message: "Activity logged", id: result.id }); + } catch (err) { + homepageLogger.error("Failed to log activity", err); + res.status(500).json({ error: "Failed to log activity" }); + } +}); + +// Reset recent activity for current user +app.delete("/activity/reset", async (req, res) => { + try { + const userId = (req as AuthenticatedRequest).userId; + + if (!SimpleDBOps.isUserDataUnlocked(userId)) { + return res.status(401).json({ + error: "Session expired - please log in again", + code: "SESSION_EXPIRED", + }); + } + + // Delete all activities for the user + const activities = await SimpleDBOps.select( + getDb() + .select() + .from(recentActivity) + .where(eq(recentActivity.userId, userId)), + "recent_activity", + userId, + ); + + for (const activity of activities) { + await SimpleDBOps.delete(recentActivity, "recent_activity", userId); + } + + res.json({ message: "Recent activity cleared" }); + } catch (err) { + homepageLogger.error("Failed to reset activity", err); + res.status(500).json({ error: "Failed to reset activity" }); + } +}); + +const PORT = 30006; +app.listen(PORT, async () => { + try { + await authManager.initialize(); + } catch (err) { + homepageLogger.error("Failed to initialize AuthManager", err, { + operation: "auth_init_error", + }); + } +}); diff --git a/src/backend/ssh/file-manager.ts b/src/backend/ssh/file-manager.ts index 99ce1e95..9f3d83cb 100644 --- a/src/backend/ssh/file-manager.ts +++ b/src/backend/ssh/file-manager.ts @@ -1,13 +1,15 @@ import express from "express"; import cors from "cors"; import cookieParser from "cookie-parser"; +import axios from "axios"; import { Client as SSHClient } from "ssh2"; import { getDb } from "../database/db/index.js"; -import { sshCredentials } from "../database/db/schema.js"; +import { sshCredentials, sshData } from "../database/db/schema.js"; import { eq, and } from "drizzle-orm"; import { fileLogger } from "../utils/logger.js"; import { SimpleDBOps } from "../utils/simple-db-ops.js"; import { AuthManager } from "../utils/auth-manager.js"; +import type { AuthenticatedRequest } from "../../types/index.js"; function isExecutableFile(permissions: string, fileName: string): boolean { const hasExecutePermission = @@ -94,14 +96,33 @@ interface SSHSession { timeout?: NodeJS.Timeout; } +interface PendingTOTPSession { + client: SSHClient; + finish: (responses: string[]) => void; + config: import("ssh2").ConnectConfig; + createdAt: number; + sessionId: string; + hostId?: number; + ip?: string; + port?: number; + username?: string; + userId?: string; + prompts?: Array<{ prompt: string; echo: boolean }>; + totpPromptIndex?: number; + resolvedPassword?: string; +} + const sshSessions: Record = {}; +const pendingTOTPSessions: Record = {}; function cleanupSession(sessionId: string) { const session = sshSessions[sessionId]; if (session) { try { session.client.end(); - } catch {} + } catch { + // Ignore connection close errors + } clearTimeout(session.timeout); delete sshSessions[sessionId]; } @@ -155,7 +176,7 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { credentialId, } = req.body; - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!userId) { fileLogger.error("SSH connection rejected: no authenticated user", { @@ -235,10 +256,11 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { ); } - const config: any = { + const config: Record = { host: ip, port: port || 22, username, + tryKeyboard: true, readyTimeout: 60000, keepaliveInterval: 30000, keepaliveCountMax: 3, @@ -277,12 +299,6 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { }; if ( - resolvedCredentials.authType === "password" && - resolvedCredentials.password && - resolvedCredentials.password.trim() - ) { - config.password = resolvedCredentials.password; - } else if ( resolvedCredentials.authType === "key" && resolvedCredentials.sshKey && resolvedCredentials.sshKey.trim() @@ -313,6 +329,22 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { }); return res.status(400).json({ error: "Invalid SSH key format" }); } + } else if (resolvedCredentials.authType === "password") { + if (!resolvedCredentials.password || !resolvedCredentials.password.trim()) { + fileLogger.warn( + "Password authentication requested but no password provided", + { + operation: "file_connect", + sessionId, + hostId, + }, + ); + return res + .status(400) + .json({ error: "Password required for password authentication" }); + } + // Set password to offer both password and keyboard-interactive methods + config.password = resolvedCredentials.password; } else { fileLogger.warn( "No valid authentication method provided for file manager", @@ -342,6 +374,56 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { }; scheduleSessionCleanup(sessionId); res.json({ status: "success", message: "SSH connection established" }); + + // Log activity to homepage API + if (hostId && userId) { + (async () => { + try { + const hosts = await SimpleDBOps.select( + getDb() + .select() + .from(sshData) + .where(and(eq(sshData.id, hostId), eq(sshData.userId, userId))), + "ssh_data", + userId, + ); + + const hostName = + hosts.length > 0 && hosts[0].name + ? hosts[0].name + : `${username}@${ip}:${port}`; + + const authManager = AuthManager.getInstance(); + await axios.post( + "http://localhost:30006/activity/log", + { + type: "file_manager", + hostId, + hostName, + }, + { + headers: { + Authorization: `Bearer ${await authManager.generateJWTToken(userId)}`, + }, + }, + ); + + fileLogger.info("File manager activity logged", { + operation: "activity_log", + userId, + hostId, + hostName, + }); + } catch (error) { + fileLogger.warn("Failed to log file manager activity", { + operation: "activity_log_error", + userId, + hostId, + error: error instanceof Error ? error.message : "Unknown error", + }); + } + })(); + } }); client.on("error", (err) => { @@ -364,9 +446,290 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { cleanupSession(sessionId); }); + client.on( + "keyboard-interactive", + ( + name: string, + instructions: string, + instructionsLang: string, + prompts: Array<{ prompt: string; echo: boolean }>, + finish: (responses: string[]) => void, + ) => { + fileLogger.info("Keyboard-interactive authentication requested", { + operation: "file_keyboard_interactive", + hostId, + sessionId, + promptsCount: prompts.length, + }); + + const totpPromptIndex = prompts.findIndex((p) => + /verification code|verification_code|token|otp|2fa|authenticator|google.*auth/i.test( + p.prompt, + ), + ); + + if (totpPromptIndex !== -1) { + if (responseSent) return; + responseSent = true; + + if (pendingTOTPSessions[sessionId]) { + fileLogger.warn( + "TOTP session already exists, ignoring duplicate keyboard-interactive", + { + operation: "file_keyboard_interactive", + hostId, + sessionId, + }, + ); + // Don't respond to duplicate keyboard-interactive events + // The first one is still being processed + return; + } + + pendingTOTPSessions[sessionId] = { + client, + finish, + config, + createdAt: Date.now(), + sessionId, + hostId, + ip, + port, + username, + userId, + prompts, + totpPromptIndex, + resolvedPassword: resolvedCredentials.password, + }; + + fileLogger.info("Created TOTP session", { + operation: "file_keyboard_interactive_totp", + hostId, + sessionId, + prompt: prompts[totpPromptIndex].prompt, + promptsCount: prompts.length, + }); + + res.json({ + requires_totp: true, + sessionId, + prompt: prompts[totpPromptIndex].prompt, + }); + } else { + if (resolvedCredentials.password) { + const responses = prompts.map( + () => resolvedCredentials.password || "", + ); + finish(responses); + } else { + finish(prompts.map(() => "")); + } + } + }, + ); + client.connect(config); }); +app.post("/ssh/file_manager/ssh/connect-totp", async (req, res) => { + const { sessionId, totpCode } = req.body; + + const userId = (req as AuthenticatedRequest).userId; + + if (!userId) { + fileLogger.error("TOTP verification rejected: no authenticated user", { + operation: "file_totp_auth", + sessionId, + }); + return res.status(401).json({ error: "Authentication required" }); + } + + if (!sessionId || !totpCode) { + return res.status(400).json({ error: "Session ID and TOTP code required" }); + } + + const session = pendingTOTPSessions[sessionId]; + + if (!session) { + fileLogger.warn("TOTP session not found or expired", { + operation: "file_totp_verify", + sessionId, + userId, + availableSessions: Object.keys(pendingTOTPSessions), + }); + return res + .status(404) + .json({ error: "TOTP session expired. Please reconnect." }); + } + + if (Date.now() - session.createdAt > 180000) { + delete pendingTOTPSessions[sessionId]; + try { + session.client.end(); + } catch { + // Ignore errors when closing timed out session + } + fileLogger.warn("TOTP session timeout before code submission", { + operation: "file_totp_verify", + sessionId, + userId, + age: Date.now() - session.createdAt, + }); + return res + .status(408) + .json({ error: "TOTP session timeout. Please reconnect." }); + } + + fileLogger.info("Submitting TOTP code to SSH server", { + operation: "file_totp_verify", + sessionId, + userId, + codeLength: totpCode.length, + promptsCount: session.prompts?.length || 0, + }); + + // Build responses for ALL prompts, just like in terminal.ts + const responses = (session.prompts || []).map((p, index) => { + if (index === session.totpPromptIndex) { + return totpCode; + } + if (/password/i.test(p.prompt) && session.resolvedPassword) { + return session.resolvedPassword; + } + return ""; + }); + + fileLogger.info("Full keyboard-interactive response for file manager", { + operation: "file_totp_full_response", + sessionId, + userId, + totalPrompts: session.prompts?.length || 0, + responsesProvided: responses.filter((r) => r !== "").length, + }); + + let responseSent = false; + let responseTimeout: NodeJS.Timeout; + + // Remove old event listeners from /connect endpoint to avoid conflicts + session.client.removeAllListeners("ready"); + session.client.removeAllListeners("error"); + + // CRITICAL: Attach event listeners BEFORE calling finish() to avoid race condition + session.client.once("ready", () => { + if (responseSent) return; + responseSent = true; + clearTimeout(responseTimeout); + + delete pendingTOTPSessions[sessionId]; + + sshSessions[sessionId] = { + client: session.client, + isConnected: true, + lastActive: Date.now(), + }; + scheduleSessionCleanup(sessionId); + + fileLogger.success("TOTP verification successful", { + operation: "file_totp_verify", + sessionId, + userId, + }); + + res.json({ + status: "success", + message: "TOTP verified, SSH connection established", + }); + + // Log activity to homepage API + if (session.hostId && session.userId) { + (async () => { + try { + const hosts = await SimpleDBOps.select( + getDb() + .select() + .from(sshData) + .where( + and( + eq(sshData.id, session.hostId!), + eq(sshData.userId, session.userId!), + ), + ), + "ssh_data", + session.userId!, + ); + + const hostName = + hosts.length > 0 && hosts[0].name + ? hosts[0].name + : `${session.username}@${session.ip}:${session.port}`; + + const authManager = AuthManager.getInstance(); + await axios.post( + "http://localhost:30006/activity/log", + { + type: "file_manager", + hostId: session.hostId, + hostName, + }, + { + headers: { + Authorization: `Bearer ${await authManager.generateJWTToken(session.userId!)}`, + }, + }, + ); + + fileLogger.info("File manager activity logged (TOTP)", { + operation: "activity_log", + userId: session.userId, + hostId: session.hostId, + hostName, + }); + } catch (error) { + fileLogger.warn("Failed to log file manager activity (TOTP)", { + operation: "activity_log_error", + userId: session.userId, + hostId: session.hostId, + error: error instanceof Error ? error.message : "Unknown error", + }); + } + })(); + } + }); + + session.client.once("error", (err) => { + if (responseSent) return; + responseSent = true; + clearTimeout(responseTimeout); + + delete pendingTOTPSessions[sessionId]; + + fileLogger.error("TOTP verification failed", { + operation: "file_totp_verify", + sessionId, + userId, + error: err.message, + }); + + res.status(401).json({ status: "error", message: "Invalid TOTP code" }); + }); + + responseTimeout = setTimeout(() => { + if (!responseSent) { + responseSent = true; + delete pendingTOTPSessions[sessionId]; + fileLogger.warn("TOTP verification timeout", { + operation: "file_totp_verify", + sessionId, + userId, + }); + res.status(408).json({ error: "TOTP verification timeout" }); + } + }, 60000); + + // Now that event listeners are attached, submit the TOTP response + session.finish(responses); +}); + app.post("/ssh/file_manager/ssh/disconnect", (req, res) => { const { sessionId } = req.body; cleanupSession(sessionId); @@ -455,13 +818,12 @@ app.get("/ssh/file_manager/ssh/listFiles", (req, res) => { const parts = line.split(/\s+/); if (parts.length >= 9) { const permissions = parts[0]; - const linkCount = parts[1]; const owner = parts[2]; const group = parts[3]; const size = parseInt(parts[4], 10); let dateStr = ""; - let nameStartIndex = 8; + const nameStartIndex = 8; if (parts[5] && parts[6] && parts[7]) { dateStr = `${parts[5]} ${parts[6]} ${parts[7]}`; @@ -694,7 +1056,7 @@ app.get("/ssh/file_manager/ssh/readFile", (req, res) => { }); app.post("/ssh/file_manager/ssh/writeFile", async (req, res) => { - const { sessionId, path: filePath, content, hostId, userId } = req.body; + const { sessionId, path: filePath, content } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -881,14 +1243,7 @@ app.post("/ssh/file_manager/ssh/writeFile", async (req, res) => { }); app.post("/ssh/file_manager/ssh/uploadFile", async (req, res) => { - const { - sessionId, - path: filePath, - content, - fileName, - hostId, - userId, - } = req.body; + const { sessionId, path: filePath, content, fileName } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -1022,8 +1377,6 @@ app.post("/ssh/file_manager/ssh/uploadFile", async (req, res) => { } if (chunks.length === 1) { - const tempFile = `/tmp/upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - const escapedTempFile = tempFile.replace(/'/g, "'\"'\"'"); const escapedPath = fullPath.replace(/'/g, "'\"'\"'"); const writeCommand = `echo '${chunks[0]}' | base64 -d > '${escapedPath}' && echo "SUCCESS"`; @@ -1088,13 +1441,11 @@ app.post("/ssh/file_manager/ssh/uploadFile", async (req, res) => { }); }); } else { - const tempFile = `/tmp/upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - const escapedTempFile = tempFile.replace(/'/g, "'\"'\"'"); const escapedPath = fullPath.replace(/'/g, "'\"'\"'"); let writeCommand = `> '${escapedPath}'`; - chunks.forEach((chunk, index) => { + chunks.forEach((chunk) => { writeCommand += ` && echo '${chunk}' | base64 -d >> '${escapedPath}'`; }); @@ -1177,14 +1528,7 @@ app.post("/ssh/file_manager/ssh/uploadFile", async (req, res) => { }); app.post("/ssh/file_manager/ssh/createFile", async (req, res) => { - const { - sessionId, - path: filePath, - fileName, - content = "", - hostId, - userId, - } = req.body; + const { sessionId, path: filePath, fileName } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -1285,7 +1629,7 @@ app.post("/ssh/file_manager/ssh/createFile", async (req, res) => { }); app.post("/ssh/file_manager/ssh/createFolder", async (req, res) => { - const { sessionId, path: folderPath, folderName, hostId, userId } = req.body; + const { sessionId, path: folderPath, folderName } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -1386,7 +1730,7 @@ app.post("/ssh/file_manager/ssh/createFolder", async (req, res) => { }); app.delete("/ssh/file_manager/ssh/deleteItem", async (req, res) => { - const { sessionId, path: itemPath, isDirectory, hostId, userId } = req.body; + const { sessionId, path: itemPath, isDirectory } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -1488,7 +1832,7 @@ app.delete("/ssh/file_manager/ssh/deleteItem", async (req, res) => { }); app.put("/ssh/file_manager/ssh/renameItem", async (req, res) => { - const { sessionId, oldPath, newName, hostId, userId } = req.body; + const { sessionId, oldPath, newName } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -1596,7 +1940,7 @@ app.put("/ssh/file_manager/ssh/renameItem", async (req, res) => { }); app.put("/ssh/file_manager/ssh/moveItem", async (req, res) => { - const { sessionId, oldPath, newPath, hostId, userId } = req.body; + const { sessionId, oldPath, newPath } = req.body; const sshConn = sshSessions[sessionId]; if (!sessionId) { @@ -1985,7 +2329,7 @@ app.post("/ssh/file_manager/ssh/copyItem", async (req, res) => { }); app.post("/ssh/file_manager/ssh/executeFile", async (req, res) => { - const { sessionId, filePath, hostId, userId } = req.body; + const { sessionId, filePath } = req.body; const sshConn = sshSessions[sessionId]; if (!sshConn || !sshConn.isConnected) { @@ -2022,7 +2366,7 @@ app.post("/ssh/file_manager/ssh/executeFile", async (req, res) => { checkResult += data.toString(); }); - checkStream.on("close", (code) => { + checkStream.on("close", () => { if (!checkResult.includes("EXECUTABLE")) { return res.status(400).json({ error: "File is not executable" }); } diff --git a/src/backend/ssh/server-stats.ts b/src/backend/ssh/server-stats.ts index cc8c7e29..42ab41c7 100644 --- a/src/backend/ssh/server-stats.ts +++ b/src/backend/ssh/server-stats.ts @@ -9,6 +9,7 @@ import { eq, and } from "drizzle-orm"; import { statsLogger } from "../utils/logger.js"; import { SimpleDBOps } from "../utils/simple-db-ops.js"; import { AuthManager } from "../utils/auth-manager.js"; +import type { AuthenticatedRequest } from "../../types/index.js"; interface PooledConnection { client: Client; @@ -60,7 +61,7 @@ class SSHConnectionPool { return client; } - return new Promise((resolve, reject) => { + return new Promise((resolve) => { const checkAvailable = () => { const available = connections.find((conn) => !conn.inUse); if (available) { @@ -95,6 +96,44 @@ class SSHConnectionPool { reject(err); }); + client.on( + "keyboard-interactive", + ( + name: string, + instructions: string, + instructionsLang: string, + prompts: Array<{ prompt: string; echo: boolean }>, + finish: (responses: string[]) => void, + ) => { + const totpPrompt = prompts.find((p) => + /verification code|verification_code|token|otp|2fa|authenticator|google.*auth/i.test( + p.prompt, + ), + ); + + if (totpPrompt) { + statsLogger.warn( + `Server Stats cannot handle TOTP for host ${host.ip}. Connection will fail.`, + { + operation: "server_stats_totp_detected", + hostId: host.id, + }, + ); + client.end(); + reject( + new Error( + "TOTP authentication required but not supported in Server Stats", + ), + ); + } else if (host.password) { + const responses = prompts.map(() => host.password || ""); + finish(responses); + } else { + finish(prompts.map(() => "")); + } + }, + ); + try { client.connect(buildSshConfig(host)); } catch (err) { @@ -123,7 +162,9 @@ class SSHConnectionPool { if (!conn.inUse && now - conn.lastUsed > maxAge) { try { conn.client.end(); - } catch {} + } catch { + // Ignore errors when closing stale connections + } return false; } return true; @@ -143,7 +184,9 @@ class SSHConnectionPool { for (const conn of connections) { try { conn.client.end(); - } catch {} + } catch { + // Ignore errors when closing connections during cleanup + } } } this.connections.clear(); @@ -151,7 +194,7 @@ class SSHConnectionPool { } class RequestQueue { - private queues = new Map Promise>>(); + private queues = new Map Promise>>(); private processing = new Set(); async queueRequest(hostId: number, request: () => Promise): Promise { @@ -181,7 +224,9 @@ class RequestQueue { if (request) { try { await request(); - } catch (error) {} + } catch { + // Ignore errors from queued requests + } } } @@ -193,7 +238,7 @@ class RequestQueue { } interface CachedMetrics { - data: any; + data: unknown; timestamp: number; hostId: number; } @@ -202,7 +247,7 @@ class MetricsCache { private cache = new Map(); private ttl = 30000; - get(hostId: number): any | null { + get(hostId: number): unknown | null { const cached = this.cache.get(hostId); if (cached && Date.now() - cached.timestamp < this.ttl) { return cached.data; @@ -210,7 +255,7 @@ class MetricsCache { return null; } - set(hostId: number, data: any): void { + set(hostId: number, data: unknown): void { this.cache.set(hostId, { data, timestamp: Date.now(), @@ -253,7 +298,8 @@ interface SSHHostWithCredentials { enableTunnel: boolean; enableFileManager: boolean; defaultPath: string; - tunnelConnections: any[]; + tunnelConnections: unknown[]; + statsConfig?: string; createdAt: string; updatedAt: string; userId: string; @@ -387,11 +433,11 @@ async function fetchHostById( } async function resolveHostCredentials( - host: any, + host: Record, userId: string, ): Promise { try { - const baseHost: any = { + const baseHost: Record = { id: host.id, name: host.name, ip: host.ip, @@ -411,8 +457,9 @@ async function resolveHostCredentials( enableFileManager: !!host.enableFileManager, defaultPath: host.defaultPath || "/", tunnelConnections: host.tunnelConnections - ? JSON.parse(host.tunnelConnections) + ? JSON.parse(host.tunnelConnections as string) : [], + statsConfig: host.statsConfig || undefined, createdAt: host.createdAt, updatedAt: host.updatedAt, userId: host.userId, @@ -426,7 +473,7 @@ async function resolveHostCredentials( .from(sshCredentials) .where( and( - eq(sshCredentials.id, host.credentialId), + eq(sshCredentials.id, host.credentialId as number), eq(sshCredentials.userId, userId), ), ), @@ -466,7 +513,7 @@ async function resolveHostCredentials( addLegacyCredentials(baseHost, host); } - return baseHost; + return baseHost as unknown as SSHHostWithCredentials; } catch (error) { statsLogger.error( `Failed to resolve host credentials for host ${host.id}: ${error instanceof Error ? error.message : "Unknown error"}`, @@ -475,7 +522,10 @@ async function resolveHostCredentials( } } -function addLegacyCredentials(baseHost: any, host: any): void { +function addLegacyCredentials( + baseHost: Record, + host: Record, +): void { baseHost.password = host.password || null; baseHost.key = host.key || null; baseHost.keyPassword = host.key_password || host.keyPassword || null; @@ -487,6 +537,7 @@ function buildSshConfig(host: SSHHostWithCredentials): ConnectConfig { host: host.ip, port: host.port || 22, username: host.username || "root", + tryKeyboard: true, readyTimeout: 10_000, algorithms: { kex: [ @@ -526,7 +577,7 @@ function buildSshConfig(host: SSHHostWithCredentials): ConnectConfig { if (!host.password) { throw new Error(`No password available for host ${host.ip}`); } - (base as any).password = host.password; + base.password = host.password; } else if (host.authType === "key") { if (!host.key) { throw new Error(`No SSH key available for host ${host.ip}`); @@ -542,10 +593,13 @@ function buildSshConfig(host: SSHHostWithCredentials): ConnectConfig { .replace(/\r\n/g, "\n") .replace(/\r/g, "\n"); - (base as any).privateKey = Buffer.from(cleanKey, "utf8"); + (base as Record).privateKey = Buffer.from( + cleanKey, + "utf8", + ); if (host.keyPassword) { - (base as any).passphrase = host.keyPassword; + (base as Record).passphrase = host.keyPassword; } } catch (keyError) { statsLogger.error( @@ -643,175 +697,387 @@ async function collectMetrics(host: SSHHostWithCredentials): Promise<{ percent: number | null; usedHuman: string | null; totalHuman: string | null; + availableHuman: string | null; + }; + network: { + interfaces: Array<{ + name: string; + ip: string; + state: string; + rxBytes: string | null; + txBytes: string | null; + }>; + }; + uptime: { + seconds: number | null; + formatted: string | null; + }; + processes: { + total: number | null; + running: number | null; + top: Array<{ + pid: string; + user: string; + cpu: string; + mem: string; + command: string; + }>; + }; + system: { + hostname: string | null; + kernel: string | null; + os: string | null; }; }> { const cached = metricsCache.get(host.id); if (cached) { - return cached; + return cached as ReturnType extends Promise + ? T + : never; } return requestQueue.queueRequest(host.id, async () => { - return withSshConnection(host, async (client) => { - let cpuPercent: number | null = null; - let cores: number | null = null; - let loadTriplet: [number, number, number] | null = null; + try { + return await withSshConnection(host, async (client) => { + let cpuPercent: number | null = null; + let cores: number | null = null; + let loadTriplet: [number, number, number] | null = null; - try { - const [stat1, loadAvgOut, coresOut] = await Promise.all([ - execCommand(client, "cat /proc/stat"), - execCommand(client, "cat /proc/loadavg"), - execCommand( - client, - "nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo", - ), - ]); + try { + const [stat1, loadAvgOut, coresOut] = await Promise.all([ + execCommand(client, "cat /proc/stat"), + execCommand(client, "cat /proc/loadavg"), + execCommand( + client, + "nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo", + ), + ]); - await new Promise((r) => setTimeout(r, 500)); - const stat2 = await execCommand(client, "cat /proc/stat"); + await new Promise((r) => setTimeout(r, 500)); + const stat2 = await execCommand(client, "cat /proc/stat"); - const cpuLine1 = ( - stat1.stdout.split("\n").find((l) => l.startsWith("cpu ")) || "" - ).trim(); - const cpuLine2 = ( - stat2.stdout.split("\n").find((l) => l.startsWith("cpu ")) || "" - ).trim(); - const a = parseCpuLine(cpuLine1); - const b = parseCpuLine(cpuLine2); - if (a && b) { - const totalDiff = b.total - a.total; - const idleDiff = b.idle - a.idle; - const used = totalDiff - idleDiff; - if (totalDiff > 0) - cpuPercent = Math.max(0, Math.min(100, (used / totalDiff) * 100)); - } - - const laParts = loadAvgOut.stdout.trim().split(/\s+/); - if (laParts.length >= 3) { - loadTriplet = [ - Number(laParts[0]), - Number(laParts[1]), - Number(laParts[2]), - ].map((v) => (Number.isFinite(v) ? Number(v) : 0)) as [ - number, - number, - number, - ]; - } - - const coresNum = Number((coresOut.stdout || "").trim()); - cores = Number.isFinite(coresNum) && coresNum > 0 ? coresNum : null; - } catch (e) { - statsLogger.warn( - `Failed to collect CPU metrics for host ${host.id}`, - e, - ); - cpuPercent = null; - cores = null; - loadTriplet = null; - } - - let memPercent: number | null = null; - let usedGiB: number | null = null; - let totalGiB: number | null = null; - try { - const memInfo = await execCommand(client, "cat /proc/meminfo"); - const lines = memInfo.stdout.split("\n"); - const getVal = (key: string) => { - const line = lines.find((l) => l.startsWith(key)); - if (!line) return null; - const m = line.match(/\d+/); - return m ? Number(m[0]) : null; - }; - const totalKb = getVal("MemTotal:"); - const availKb = getVal("MemAvailable:"); - if (totalKb && availKb && totalKb > 0) { - const usedKb = totalKb - availKb; - memPercent = Math.max(0, Math.min(100, (usedKb / totalKb) * 100)); - usedGiB = kibToGiB(usedKb); - totalGiB = kibToGiB(totalKb); - } - } catch (e) { - statsLogger.warn( - `Failed to collect memory metrics for host ${host.id}`, - e, - ); - memPercent = null; - usedGiB = null; - totalGiB = null; - } - - let diskPercent: number | null = null; - let usedHuman: string | null = null; - let totalHuman: string | null = null; - let availableHuman: string | null = null; - try { - const [diskOutHuman, diskOutBytes] = await Promise.all([ - execCommand(client, "df -h -P / | tail -n +2"), - execCommand(client, "df -B1 -P / | tail -n +2"), - ]); - - const humanLine = - diskOutHuman.stdout - .split("\n") - .map((l) => l.trim()) - .filter(Boolean)[0] || ""; - const bytesLine = - diskOutBytes.stdout - .split("\n") - .map((l) => l.trim()) - .filter(Boolean)[0] || ""; - - const humanParts = humanLine.split(/\s+/); - const bytesParts = bytesLine.split(/\s+/); - - if (humanParts.length >= 6 && bytesParts.length >= 6) { - totalHuman = humanParts[1] || null; - usedHuman = humanParts[2] || null; - availableHuman = humanParts[3] || null; - - const totalBytes = Number(bytesParts[1]); - const usedBytes = Number(bytesParts[2]); - - if ( - Number.isFinite(totalBytes) && - Number.isFinite(usedBytes) && - totalBytes > 0 - ) { - diskPercent = Math.max( - 0, - Math.min(100, (usedBytes / totalBytes) * 100), - ); + const cpuLine1 = ( + stat1.stdout.split("\n").find((l) => l.startsWith("cpu ")) || "" + ).trim(); + const cpuLine2 = ( + stat2.stdout.split("\n").find((l) => l.startsWith("cpu ")) || "" + ).trim(); + const a = parseCpuLine(cpuLine1); + const b = parseCpuLine(cpuLine2); + if (a && b) { + const totalDiff = b.total - a.total; + const idleDiff = b.idle - a.idle; + const used = totalDiff - idleDiff; + if (totalDiff > 0) + cpuPercent = Math.max(0, Math.min(100, (used / totalDiff) * 100)); } + + const laParts = loadAvgOut.stdout.trim().split(/\s+/); + if (laParts.length >= 3) { + loadTriplet = [ + Number(laParts[0]), + Number(laParts[1]), + Number(laParts[2]), + ].map((v) => (Number.isFinite(v) ? Number(v) : 0)) as [ + number, + number, + number, + ]; + } + + const coresNum = Number((coresOut.stdout || "").trim()); + cores = Number.isFinite(coresNum) && coresNum > 0 ? coresNum : null; + } catch (e) { + statsLogger.warn( + `Failed to collect CPU metrics for host ${host.id}`, + e, + ); + cpuPercent = null; + cores = null; + loadTriplet = null; } - } catch (e) { - statsLogger.warn( - `Failed to collect disk metrics for host ${host.id}`, - e, - ); - diskPercent = null; - usedHuman = null; - totalHuman = null; - availableHuman = null; + + let memPercent: number | null = null; + let usedGiB: number | null = null; + let totalGiB: number | null = null; + try { + const memInfo = await execCommand(client, "cat /proc/meminfo"); + const lines = memInfo.stdout.split("\n"); + const getVal = (key: string) => { + const line = lines.find((l) => l.startsWith(key)); + if (!line) return null; + const m = line.match(/\d+/); + return m ? Number(m[0]) : null; + }; + const totalKb = getVal("MemTotal:"); + const availKb = getVal("MemAvailable:"); + if (totalKb && availKb && totalKb > 0) { + const usedKb = totalKb - availKb; + memPercent = Math.max(0, Math.min(100, (usedKb / totalKb) * 100)); + usedGiB = kibToGiB(usedKb); + totalGiB = kibToGiB(totalKb); + } + } catch (e) { + statsLogger.warn( + `Failed to collect memory metrics for host ${host.id}`, + e, + ); + memPercent = null; + usedGiB = null; + totalGiB = null; + } + + let diskPercent: number | null = null; + let usedHuman: string | null = null; + let totalHuman: string | null = null; + let availableHuman: string | null = null; + try { + const [diskOutHuman, diskOutBytes] = await Promise.all([ + execCommand(client, "df -h -P / | tail -n +2"), + execCommand(client, "df -B1 -P / | tail -n +2"), + ]); + + const humanLine = + diskOutHuman.stdout + .split("\n") + .map((l) => l.trim()) + .filter(Boolean)[0] || ""; + const bytesLine = + diskOutBytes.stdout + .split("\n") + .map((l) => l.trim()) + .filter(Boolean)[0] || ""; + + const humanParts = humanLine.split(/\s+/); + const bytesParts = bytesLine.split(/\s+/); + + if (humanParts.length >= 6 && bytesParts.length >= 6) { + totalHuman = humanParts[1] || null; + usedHuman = humanParts[2] || null; + availableHuman = humanParts[3] || null; + + const totalBytes = Number(bytesParts[1]); + const usedBytes = Number(bytesParts[2]); + + if ( + Number.isFinite(totalBytes) && + Number.isFinite(usedBytes) && + totalBytes > 0 + ) { + diskPercent = Math.max( + 0, + Math.min(100, (usedBytes / totalBytes) * 100), + ); + } + } + } catch (e) { + statsLogger.warn( + `Failed to collect disk metrics for host ${host.id}`, + e, + ); + diskPercent = null; + usedHuman = null; + totalHuman = null; + availableHuman = null; + } + + // Collect network interfaces + const interfaces: Array<{ + name: string; + ip: string; + state: string; + rxBytes: string | null; + txBytes: string | null; + }> = []; + try { + const ifconfigOut = await execCommand( + client, + "ip -o addr show | awk '{print $2,$4}' | grep -v '^lo'", + ); + const netStatOut = await execCommand( + client, + "ip -o link show | awk '{print $2,$9}' | sed 's/:$//'", + ); + + const addrs = ifconfigOut.stdout + .split("\n") + .map((l) => l.trim()) + .filter(Boolean); + const states = netStatOut.stdout + .split("\n") + .map((l) => l.trim()) + .filter(Boolean); + + const ifMap = new Map(); + for (const line of addrs) { + const parts = line.split(/\s+/); + if (parts.length >= 2) { + const name = parts[0]; + const ip = parts[1].split("/")[0]; + if (!ifMap.has(name)) ifMap.set(name, { ip, state: "UNKNOWN" }); + } + } + for (const line of states) { + const parts = line.split(/\s+/); + if (parts.length >= 2) { + const name = parts[0]; + const state = parts[1]; + const existing = ifMap.get(name); + if (existing) { + existing.state = state; + } + } + } + + for (const [name, data] of ifMap.entries()) { + interfaces.push({ + name, + ip: data.ip, + state: data.state, + rxBytes: null, + txBytes: null, + }); + } + } catch (e) { + statsLogger.warn( + `Failed to collect network metrics for host ${host.id}`, + e, + ); + } + + // Collect uptime + let uptimeSeconds: number | null = null; + let uptimeFormatted: string | null = null; + try { + const uptimeOut = await execCommand(client, "cat /proc/uptime"); + const uptimeParts = uptimeOut.stdout.trim().split(/\s+/); + if (uptimeParts.length >= 1) { + uptimeSeconds = Number(uptimeParts[0]); + if (Number.isFinite(uptimeSeconds)) { + const days = Math.floor(uptimeSeconds / 86400); + const hours = Math.floor((uptimeSeconds % 86400) / 3600); + const minutes = Math.floor((uptimeSeconds % 3600) / 60); + uptimeFormatted = `${days}d ${hours}h ${minutes}m`; + } + } + } catch (e) { + statsLogger.warn(`Failed to collect uptime for host ${host.id}`, e); + } + + // Collect process information + let totalProcesses: number | null = null; + let runningProcesses: number | null = null; + const topProcesses: Array<{ + pid: string; + user: string; + cpu: string; + mem: string; + command: string; + }> = []; + try { + const psOut = await execCommand( + client, + "ps aux --sort=-%cpu | head -n 11", + ); + const psLines = psOut.stdout + .split("\n") + .map((l) => l.trim()) + .filter(Boolean); + if (psLines.length > 1) { + for (let i = 1; i < Math.min(psLines.length, 11); i++) { + const parts = psLines[i].split(/\s+/); + if (parts.length >= 11) { + topProcesses.push({ + pid: parts[1], + user: parts[0], + cpu: parts[2], + mem: parts[3], + command: parts.slice(10).join(" ").substring(0, 50), + }); + } + } + } + + const procCount = await execCommand(client, "ps aux | wc -l"); + const runningCount = await execCommand( + client, + "ps aux | grep -c ' R '", + ); + totalProcesses = Number(procCount.stdout.trim()) - 1; + runningProcesses = Number(runningCount.stdout.trim()); + } catch (e) { + statsLogger.warn( + `Failed to collect process info for host ${host.id}`, + e, + ); + } + + // Collect system information + let hostname: string | null = null; + let kernel: string | null = null; + let os: string | null = null; + try { + const hostnameOut = await execCommand(client, "hostname"); + const kernelOut = await execCommand(client, "uname -r"); + const osOut = await execCommand( + client, + "cat /etc/os-release | grep '^PRETTY_NAME=' | cut -d'\"' -f2", + ); + + hostname = hostnameOut.stdout.trim() || null; + kernel = kernelOut.stdout.trim() || null; + os = osOut.stdout.trim() || null; + } catch (e) { + statsLogger.warn( + `Failed to collect system info for host ${host.id}`, + e, + ); + } + + const result = { + cpu: { percent: toFixedNum(cpuPercent, 0), cores, load: loadTriplet }, + memory: { + percent: toFixedNum(memPercent, 0), + usedGiB: usedGiB ? toFixedNum(usedGiB, 2) : null, + totalGiB: totalGiB ? toFixedNum(totalGiB, 2) : null, + }, + disk: { + percent: toFixedNum(diskPercent, 0), + usedHuman, + totalHuman, + availableHuman, + }, + network: { + interfaces, + }, + uptime: { + seconds: uptimeSeconds, + formatted: uptimeFormatted, + }, + processes: { + total: totalProcesses, + running: runningProcesses, + top: topProcesses, + }, + system: { + hostname, + kernel, + os, + }, + }; + + metricsCache.set(host.id, result); + return result; + }); + } catch (error) { + if ( + error instanceof Error && + error.message.includes("TOTP authentication required") + ) { + throw error; } - - const result = { - cpu: { percent: toFixedNum(cpuPercent, 0), cores, load: loadTriplet }, - memory: { - percent: toFixedNum(memPercent, 0), - usedGiB: usedGiB ? toFixedNum(usedGiB, 2) : null, - totalGiB: totalGiB ? toFixedNum(totalGiB, 2) : null, - }, - disk: { - percent: toFixedNum(diskPercent, 0), - usedHuman, - totalHuman, - availableHuman, - }, - }; - - metricsCache.set(host.id, result); - return result; - }); + throw error; + } }); } @@ -829,7 +1095,9 @@ function tcpPing( settled = true; try { socket.destroy(); - } catch {} + } catch { + // Ignore errors when destroying socket + } resolve(result); }; @@ -859,8 +1127,6 @@ async function pollStatusesOnce(userId?: string): Promise { return; } - const now = new Date().toISOString(); - const checks = hosts.map(async (h) => { const isOnline = await tcpPing(h.ip, h.port, 5000); const now = new Date().toISOString(); @@ -886,7 +1152,7 @@ async function pollStatusesOnce(userId?: string): Promise { } app.get("/status", async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!SimpleDBOps.isUserDataUnlocked(userId)) { return res.status(401).json({ @@ -907,7 +1173,7 @@ app.get("/status", async (req, res) => { app.get("/status/:id", validateHostId, async (req, res) => { const id = Number(req.params.id); - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!SimpleDBOps.isUserDataUnlocked(userId)) { return res.status(401).json({ @@ -938,7 +1204,7 @@ app.get("/status/:id", validateHostId, async (req, res) => { }); app.post("/refresh", async (req, res) => { - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!SimpleDBOps.isUserDataUnlocked(userId)) { return res.status(401).json({ @@ -953,7 +1219,7 @@ app.post("/refresh", async (req, res) => { app.get("/metrics/:id", validateHostId, async (req, res) => { const id = Number(req.params.id); - const userId = (req as any).userId; + const userId = (req as AuthenticatedRequest).userId; if (!SimpleDBOps.isUserDataUnlocked(userId)) { return res.status(401).json({ @@ -974,7 +1240,16 @@ app.get("/metrics/:id", validateHostId, async (req, res) => { error: "Host is offline", cpu: { percent: null, cores: null, load: null }, memory: { percent: null, usedGiB: null, totalGiB: null }, - disk: { percent: null, usedHuman: null, totalHuman: null }, + disk: { + percent: null, + usedHuman: null, + totalHuman: null, + availableHuman: null, + }, + network: { interfaces: [] }, + uptime: { seconds: null, formatted: null }, + processes: { total: null, running: null, top: [] }, + system: { hostname: null, kernel: null, os: null }, lastChecked: new Date().toISOString(), }); } @@ -982,6 +1257,29 @@ app.get("/metrics/:id", validateHostId, async (req, res) => { const metrics = await collectMetrics(host); res.json({ ...metrics, lastChecked: new Date().toISOString() }); } catch (err) { + if ( + err instanceof Error && + err.message.includes("TOTP authentication required") + ) { + return res.status(403).json({ + error: "TOTP_REQUIRED", + message: "Server Stats unavailable for TOTP-enabled servers", + cpu: { percent: null, cores: null, load: null }, + memory: { percent: null, usedGiB: null, totalGiB: null }, + disk: { + percent: null, + usedHuman: null, + totalHuman: null, + availableHuman: null, + }, + network: { interfaces: [] }, + uptime: { seconds: null, formatted: null }, + processes: { total: null, running: null, top: [] }, + system: { hostname: null, kernel: null, os: null }, + lastChecked: new Date().toISOString(), + }); + } + statsLogger.error("Failed to collect metrics", err); if (err instanceof Error && err.message.includes("timeout")) { @@ -989,7 +1287,16 @@ app.get("/metrics/:id", validateHostId, async (req, res) => { error: "Metrics collection timeout", cpu: { percent: null, cores: null, load: null }, memory: { percent: null, usedGiB: null, totalGiB: null }, - disk: { percent: null, usedHuman: null, totalHuman: null }, + disk: { + percent: null, + usedHuman: null, + totalHuman: null, + availableHuman: null, + }, + network: { interfaces: [] }, + uptime: { seconds: null, formatted: null }, + processes: { total: null, running: null, top: [] }, + system: { hostname: null, kernel: null, os: null }, lastChecked: new Date().toISOString(), }); } @@ -998,7 +1305,16 @@ app.get("/metrics/:id", validateHostId, async (req, res) => { error: "Failed to collect metrics", cpu: { percent: null, cores: null, load: null }, memory: { percent: null, usedGiB: null, totalGiB: null }, - disk: { percent: null, usedHuman: null, totalHuman: null }, + disk: { + percent: null, + usedHuman: null, + totalHuman: null, + availableHuman: null, + }, + network: { interfaces: [] }, + uptime: { seconds: null, formatted: null }, + processes: { total: null, running: null, top: [] }, + system: { hostname: null, kernel: null, os: null }, lastChecked: new Date().toISOString(), }); } diff --git a/src/backend/ssh/terminal.ts b/src/backend/ssh/terminal.ts index 94650bd6..8c90f15a 100644 --- a/src/backend/ssh/terminal.ts +++ b/src/backend/ssh/terminal.ts @@ -1,14 +1,56 @@ import { WebSocketServer, WebSocket, type RawData } from "ws"; -import { Client, type ClientChannel, type PseudoTtyOptions } from "ssh2"; +import { + Client, + type ClientChannel, + type PseudoTtyOptions, + type ConnectConfig, +} from "ssh2"; import { parse as parseUrl } from "url"; +import axios from "axios"; import { getDb } from "../database/db/index.js"; -import { sshCredentials } from "../database/db/schema.js"; +import { sshCredentials, sshData } from "../database/db/schema.js"; import { eq, and } from "drizzle-orm"; import { sshLogger } from "../utils/logger.js"; import { SimpleDBOps } from "../utils/simple-db-ops.js"; import { AuthManager } from "../utils/auth-manager.js"; import { UserCrypto } from "../utils/user-crypto.js"; +interface ConnectToHostData { + cols: number; + rows: number; + hostConfig: { + id: number; + ip: string; + port: number; + username: string; + password?: string; + key?: string; + keyPassword?: string; + keyType?: string; + authType?: string; + credentialId?: number; + userId?: string; + }; + initialPath?: string; + executeCommand?: string; +} + +interface ResizeData { + cols: number; + rows: number; +} + +interface TOTPResponseData { + code?: string; +} + +interface WebSocketMessage { + type: string; + data?: ConnectToHostData | ResizeData | TOTPResponseData | string | unknown; + code?: string; + [key: string]: unknown; +} + const authManager = AuthManager.getInstance(); const userCrypto = UserCrypto.getInstance(); @@ -79,7 +121,6 @@ const wss = new WebSocketServer({ wss.on("connection", async (ws: WebSocket, req) => { let userId: string | undefined; - let userPayload: any; try { const url = parseUrl(req.url!, true); @@ -113,7 +154,6 @@ wss.on("connection", async (ws: WebSocket, req) => { } userId = payload.userId; - userPayload = payload; } catch (error) { sshLogger.error( "WebSocket JWT verification failed during connection", @@ -154,6 +194,8 @@ wss.on("connection", async (ws: WebSocket, req) => { let sshConn: Client | null = null; let sshStream: ClientChannel | null = null; let pingInterval: NodeJS.Timeout | null = null; + let keyboardInteractiveFinish: ((responses: string[]) => void) | null = null; + let totpPromptSent = false; ws.on("close", () => { const userWs = userConnections.get(userId); @@ -186,9 +228,9 @@ wss.on("connection", async (ws: WebSocket, req) => { return; } - let parsed: any; + let parsed: WebSocketMessage; try { - parsed = JSON.parse(msg.toString()); + parsed = JSON.parse(msg.toString()) as WebSocketMessage; } catch (e) { sshLogger.error("Invalid JSON received", e, { operation: "websocket_message_invalid_json", @@ -202,16 +244,17 @@ wss.on("connection", async (ws: WebSocket, req) => { const { type, data } = parsed; switch (type) { - case "connectToHost": - if (data.hostConfig) { - data.hostConfig.userId = userId; + case "connectToHost": { + const connectData = data as ConnectToHostData; + if (connectData.hostConfig) { + connectData.hostConfig.userId = userId; } - handleConnectToHost(data).catch((error) => { + handleConnectToHost(connectData).catch((error) => { sshLogger.error("Failed to connect to host", error, { operation: "ssh_connect", userId, - hostId: data.hostConfig?.id, - ip: data.hostConfig?.ip, + hostId: connectData.hostConfig?.id, + ip: connectData.hostConfig?.ip, }); ws.send( JSON.stringify({ @@ -223,40 +266,77 @@ wss.on("connection", async (ws: WebSocket, req) => { ); }); break; + } - case "resize": - handleResize(data); + case "resize": { + const resizeData = data as ResizeData; + handleResize(resizeData); break; + } case "disconnect": cleanupSSH(); break; - case "input": + case "input": { + const inputData = data as string; if (sshStream) { - if (data === "\t") { - sshStream.write(data); - } else if (data.startsWith("\x1b")) { - sshStream.write(data); + if (inputData === "\t") { + sshStream.write(inputData); + } else if ( + typeof inputData === "string" && + inputData.startsWith("\x1b") + ) { + sshStream.write(inputData); } else { try { - sshStream.write(Buffer.from(data, "utf8")); + sshStream.write(Buffer.from(inputData, "utf8")); } catch (error) { sshLogger.error("Error writing input to SSH stream", error, { operation: "ssh_input_encoding", userId, - dataLength: data.length, + dataLength: inputData.length, }); - sshStream.write(Buffer.from(data, "latin1")); + sshStream.write(Buffer.from(inputData, "latin1")); } } } break; + } case "ping": ws.send(JSON.stringify({ type: "pong" })); break; + case "totp_response": { + const totpData = data as TOTPResponseData; + if (keyboardInteractiveFinish && totpData?.code) { + const totpCode = totpData.code; + sshLogger.info("TOTP code received from user", { + operation: "totp_response", + userId, + codeLength: totpCode.length, + }); + + keyboardInteractiveFinish([totpCode]); + keyboardInteractiveFinish = null; + } else { + sshLogger.warn("TOTP response received but no callback available", { + operation: "totp_response_error", + userId, + hasCallback: !!keyboardInteractiveFinish, + hasCode: !!totpData?.code, + }); + ws.send( + JSON.stringify({ + type: "error", + message: "TOTP authentication state lost. Please reconnect.", + }), + ); + } + break; + } + default: sshLogger.warn("Unknown message type received", { operation: "websocket_message_unknown_type", @@ -266,26 +346,8 @@ wss.on("connection", async (ws: WebSocket, req) => { } }); - async function handleConnectToHost(data: { - cols: number; - rows: number; - hostConfig: { - id: number; - ip: string; - port: number; - username: string; - password?: string; - key?: string; - keyPassword?: string; - keyType?: string; - authType?: string; - credentialId?: number; - userId?: string; - }; - initialPath?: string; - executeCommand?: string; - }) { - const { cols, rows, hostConfig, initialPath, executeCommand } = data; + async function handleConnectToHost(data: ConnectToHostData) { + const { hostConfig, initialPath, executeCommand } = data; const { id, ip, @@ -375,12 +437,19 @@ wss.on("connection", async (ws: WebSocket, req) => { if (credentials.length > 0) { const credential = credentials[0]; resolvedCredentials = { - password: credential.password, - key: - credential.private_key || credential.privateKey || credential.key, - keyPassword: credential.key_password || credential.keyPassword, - keyType: credential.key_type || credential.keyType, - authType: credential.auth_type || credential.authType, + password: credential.password as string | undefined, + key: (credential.private_key || + credential.privateKey || + credential.key) as string | undefined, + keyPassword: (credential.key_password || credential.keyPassword) as + | string + | undefined, + keyType: (credential.key_type || credential.keyType) as + | string + | undefined, + authType: (credential.auth_type || credential.authType) as + | string + | undefined, }; } else { sshLogger.warn(`No credentials found for host ${id}`, { @@ -410,95 +479,155 @@ wss.on("connection", async (ws: WebSocket, req) => { sshConn.on("ready", () => { clearTimeout(connectionTimeout); - sshConn!.shell( - { - rows: data.rows, - cols: data.cols, - term: "xterm-256color", - } as PseudoTtyOptions, - (err, stream) => { - if (err) { - sshLogger.error("Shell error", err, { - operation: "ssh_shell", - hostId: id, - ip, - port, - username, - }); - ws.send( - JSON.stringify({ - type: "error", - message: "Shell error: " + err.message, - }), - ); - return; - } - - sshStream = stream; - - stream.on("data", (data: Buffer) => { - try { - const utf8String = data.toString("utf-8"); - ws.send(JSON.stringify({ type: "data", data: utf8String })); - } catch (error) { - sshLogger.error("Error encoding terminal data", error, { - operation: "terminal_data_encoding", + // Small delay to let connection stabilize after keyboard-interactive auth + // This helps prevent "No response from server" errors with TOTP + setTimeout(() => { + sshConn!.shell( + { + rows: data.rows, + cols: data.cols, + term: "xterm-256color", + } as PseudoTtyOptions, + (err, stream) => { + if (err) { + sshLogger.error("Shell error", err, { + operation: "ssh_shell", hostId: id, - dataLength: data.length, + ip, + port, + username, }); ws.send( JSON.stringify({ - type: "data", - data: data.toString("latin1"), + type: "error", + message: "Shell error: " + err.message, }), ); + return; } - }); - stream.on("close", () => { - ws.send( - JSON.stringify({ - type: "disconnected", - message: "Connection lost", - }), - ); - }); + sshStream = stream; - stream.on("error", (err: Error) => { - sshLogger.error("SSH stream error", err, { - operation: "ssh_stream", - hostId: id, - ip, - port, - username, + stream.on("data", (data: Buffer) => { + try { + const utf8String = data.toString("utf-8"); + ws.send(JSON.stringify({ type: "data", data: utf8String })); + } catch (error) { + sshLogger.error("Error encoding terminal data", error, { + operation: "terminal_data_encoding", + hostId: id, + dataLength: data.length, + }); + ws.send( + JSON.stringify({ + type: "data", + data: data.toString("latin1"), + }), + ); + } }); + + stream.on("close", () => { + ws.send( + JSON.stringify({ + type: "disconnected", + message: "Connection lost", + }), + ); + }); + + stream.on("error", (err: Error) => { + sshLogger.error("SSH stream error", err, { + operation: "ssh_stream", + hostId: id, + ip, + port, + username, + }); + ws.send( + JSON.stringify({ + type: "error", + message: "SSH stream error: " + err.message, + }), + ); + }); + + setupPingInterval(); + + if (initialPath && initialPath.trim() !== "") { + const cdCommand = `cd "${initialPath.replace(/"/g, '\\"')}" && pwd\n`; + stream.write(cdCommand); + } + + if (executeCommand && executeCommand.trim() !== "") { + setTimeout(() => { + const command = `${executeCommand}\n`; + stream.write(command); + }, 500); + } + ws.send( - JSON.stringify({ - type: "error", - message: "SSH stream error: " + err.message, - }), + JSON.stringify({ type: "connected", message: "SSH connected" }), ); - }); - setupPingInterval(); + // Log activity to homepage API + if (id && hostConfig.userId) { + (async () => { + try { + // Fetch host name from database + const hosts = await SimpleDBOps.select( + getDb() + .select() + .from(sshData) + .where( + and( + eq(sshData.id, id), + eq(sshData.userId, hostConfig.userId!), + ), + ), + "ssh_data", + hostConfig.userId!, + ); - if (initialPath && initialPath.trim() !== "") { - const cdCommand = `cd "${initialPath.replace(/"/g, '\\"')}" && pwd\n`; - stream.write(cdCommand); - } + const hostName = + hosts.length > 0 && hosts[0].name + ? hosts[0].name + : `${username}@${ip}:${port}`; - if (executeCommand && executeCommand.trim() !== "") { - setTimeout(() => { - const command = `${executeCommand}\n`; - stream.write(command); - }, 500); - } + await axios.post( + "http://localhost:30006/activity/log", + { + type: "terminal", + hostId: id, + hostName, + }, + { + headers: { + Authorization: `Bearer ${await authManager.generateJWTToken(hostConfig.userId!)}`, + }, + }, + ); - ws.send( - JSON.stringify({ type: "connected", message: "SSH connected" }), - ); - }, - ); + sshLogger.info("Terminal activity logged", { + operation: "activity_log", + userId: hostConfig.userId, + hostId: id, + hostName, + }); + } catch (error) { + sshLogger.warn("Failed to log terminal activity", { + operation: "activity_log_error", + userId: hostConfig.userId, + hostId: id, + error: + error instanceof Error ? error.message : "Unknown error", + }); + } + })(); + } + }, + ); + }, 100); // Small delay to stabilize connection after keyboard-interactive auth }); sshConn.on("error", (err: Error) => { @@ -557,16 +686,101 @@ wss.on("connection", async (ws: WebSocket, req) => { cleanupSSH(connectionTimeout); }); + sshConn.on( + "keyboard-interactive", + ( + name: string, + instructions: string, + instructionsLang: string, + prompts: Array<{ prompt: string; echo: boolean }>, + finish: (responses: string[]) => void, + ) => { + const promptTexts = prompts.map((p) => p.prompt); + sshLogger.info("Keyboard-interactive authentication requested", { + operation: "ssh_keyboard_interactive", + hostId: id, + promptsCount: prompts.length, + instructions: instructions || "none", + }); + console.log( + `[SSH Keyboard-Interactive] Host ${id}: ${prompts.length} prompts:`, + promptTexts, + ); + + const totpPromptIndex = prompts.findIndex((p) => + /verification code|verification_code|token|otp|2fa|authenticator|google.*auth/i.test( + p.prompt, + ), + ); + + if (totpPromptIndex !== -1) { + if (totpPromptSent) return; + totpPromptSent = true; + + keyboardInteractiveFinish = (totpResponses: string[]) => { + const totpCode = (totpResponses[0] || "").trim(); + + // Respond to ALL prompts, not just TOTP + const responses = prompts.map((p, index) => { + if (index === totpPromptIndex) { + return totpCode; + } + if (/password/i.test(p.prompt) && resolvedCredentials.password) { + return resolvedCredentials.password; + } + return ""; + }); + + sshLogger.info("TOTP response being sent to SSH server", { + operation: "totp_verification", + hostId: id, + totpCodeLength: totpCode.length, + totalPrompts: prompts.length, + responsesProvided: responses.filter((r) => r !== "").length, + }); + + finish(responses); + }; + ws.send( + JSON.stringify({ + type: "totp_required", + prompt: prompts[totpPromptIndex].prompt, + }), + ); + } else { + const responses = prompts.map((p) => { + if (/password/i.test(p.prompt) && resolvedCredentials.password) { + return resolvedCredentials.password; + } + return ""; + }); + + sshLogger.info("Responding to keyboard-interactive prompts", { + operation: "ssh_keyboard_interactive_response", + hostId: id, + hasPassword: !!resolvedCredentials.password, + responsesProvided: responses.filter((r) => r !== "").length, + totalPrompts: prompts.length, + }); + + console.log( + `[SSH Auto Response] Host ${id}: Sending ${responses.length} responses, ${responses.filter((r) => r !== "").length} non-empty`, + ); + finish(responses); + } + }, + ); + const connectConfig: any = { host: ip, port, username, + tryKeyboard: true, keepaliveInterval: 30000, keepaliveCountMax: 3, readyTimeout: 60000, tcpKeepAlive: true, tcpKeepAliveInitialDelay: 30000, - env: { TERM: "xterm-256color", LANG: "en_US.UTF-8", @@ -579,7 +793,6 @@ wss.on("connection", async (ws: WebSocket, req) => { LC_COLLATE: "en_US.UTF-8", COLORTERM: "truecolor", }, - algorithms: { kex: [ "diffie-hellman-group14-sha256", @@ -602,6 +815,15 @@ wss.on("connection", async (ws: WebSocket, req) => { "aes256-cbc", "3des-cbc", ], + serverHostKey: [ + "ssh-rsa", + "rsa-sha2-256", + "rsa-sha2-512", + "ecdsa-sha2-nistp256", + "ecdsa-sha2-nistp384", + "ecdsa-sha2-nistp521", + "ssh-ed25519", + ], hmac: [ "hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", @@ -613,15 +835,8 @@ wss.on("connection", async (ws: WebSocket, req) => { compress: ["none", "zlib@openssh.com", "zlib"], }, }; - if ( - resolvedCredentials.authType === "password" && - resolvedCredentials.password - ) { - connectConfig.password = resolvedCredentials.password; - } else if ( - resolvedCredentials.authType === "key" && - resolvedCredentials.key - ) { + + if (resolvedCredentials.authType === "key" && resolvedCredentials.key) { try { if ( !resolvedCredentials.key.includes("-----BEGIN") || @@ -640,13 +855,6 @@ wss.on("connection", async (ws: WebSocket, req) => { if (resolvedCredentials.keyPassword) { connectConfig.passphrase = resolvedCredentials.keyPassword; } - - if ( - resolvedCredentials.keyType && - resolvedCredentials.keyType !== "auto" - ) { - connectConfig.privateKeyType = resolvedCredentials.keyType; - } } catch (keyError) { sshLogger.error("SSH key format error: " + keyError.message); ws.send( @@ -666,6 +874,22 @@ wss.on("connection", async (ws: WebSocket, req) => { }), ); return; + } else if (resolvedCredentials.authType === "password") { + if (!resolvedCredentials.password) { + sshLogger.error( + "Password authentication requested but no password provided", + ); + ws.send( + JSON.stringify({ + type: "error", + message: + "Password authentication requested but no password provided", + }), + ); + return; + } + // Set password to offer both password and keyboard-interactive methods + connectConfig.password = resolvedCredentials.password; } else { sshLogger.error("No valid authentication method provided"); ws.send( @@ -680,7 +904,7 @@ wss.on("connection", async (ws: WebSocket, req) => { sshConn.connect(connectConfig); } - function handleResize(data: { cols: number; rows: number }) { + function handleResize(data: ResizeData) { if (sshStream && sshStream.setWindow) { sshStream.setWindow(data.rows, data.cols, data.rows, data.cols); ws.send( @@ -702,8 +926,11 @@ wss.on("connection", async (ws: WebSocket, req) => { if (sshStream) { try { sshStream.end(); - } catch (e: any) { - sshLogger.error("Error closing stream: " + e.message); + } catch (e: unknown) { + sshLogger.error( + "Error closing stream: " + + (e instanceof Error ? e.message : "Unknown error"), + ); } sshStream = null; } @@ -711,11 +938,17 @@ wss.on("connection", async (ws: WebSocket, req) => { if (sshConn) { try { sshConn.end(); - } catch (e: any) { - sshLogger.error("Error closing connection: " + e.message); + } catch (e: unknown) { + sshLogger.error( + "Error closing connection: " + + (e instanceof Error ? e.message : "Unknown error"), + ); } sshConn = null; } + + totpPromptSent = false; + keyboardInteractiveFinish = null; } function setupPingInterval() { @@ -723,8 +956,11 @@ wss.on("connection", async (ws: WebSocket, req) => { if (sshConn && sshStream) { try { sshStream.write("\x00"); - } catch (e: any) { - sshLogger.error("SSH keepalive failed: " + e.message); + } catch (e: unknown) { + sshLogger.error( + "SSH keepalive failed: " + + (e instanceof Error ? e.message : "Unknown error"), + ); cleanupSSH(); } } diff --git a/src/backend/ssh/tunnel.ts b/src/backend/ssh/tunnel.ts index b49606e6..afb6f095 100644 --- a/src/backend/ssh/tunnel.ts +++ b/src/backend/ssh/tunnel.ts @@ -217,7 +217,9 @@ function cleanupTunnelResources( if (verification?.timeout) clearTimeout(verification.timeout); try { verification?.conn.end(); - } catch (e) {} + } catch { + // Ignore errors + } tunnelVerifications.delete(tunnelName); } @@ -282,7 +284,9 @@ function handleDisconnect( const verification = tunnelVerifications.get(tunnelName); if (verification?.timeout) clearTimeout(verification.timeout); verification?.conn.end(); - } catch (e) {} + } catch { + // Ignore errors + } tunnelVerifications.delete(tunnelName); } @@ -511,16 +515,19 @@ async function connectSSHTunnel( if (credentials.length > 0) { const credential = credentials[0]; resolvedSourceCredentials = { - password: credential.password, - sshKey: - credential.private_key || credential.privateKey || credential.key, - keyPassword: credential.key_password || credential.keyPassword, - keyType: credential.key_type || credential.keyType, - authMethod: credential.auth_type || credential.authType, + password: credential.password as string | undefined, + sshKey: (credential.private_key || + credential.privateKey || + credential.key) as string | undefined, + keyPassword: (credential.key_password || credential.keyPassword) as + | string + | undefined, + keyType: (credential.key_type || credential.keyType) as + | string + | undefined, + authMethod: (credential.auth_type || credential.authType) as string, }; - } else { } - } else { } } catch (error) { tunnelLogger.warn("Failed to resolve source credentials from database", { @@ -591,12 +598,17 @@ async function connectSSHTunnel( if (credentials.length > 0) { const credential = credentials[0]; resolvedEndpointCredentials = { - password: credential.password, - sshKey: - credential.private_key || credential.privateKey || credential.key, - keyPassword: credential.key_password || credential.keyPassword, - keyType: credential.key_type || credential.keyType, - authMethod: credential.auth_type || credential.authType, + password: credential.password as string | undefined, + sshKey: (credential.private_key || + credential.privateKey || + credential.key) as string | undefined, + keyPassword: (credential.key_password || credential.keyPassword) as + | string + | undefined, + keyType: (credential.key_type || credential.keyType) as + | string + | undefined, + authMethod: (credential.auth_type || credential.authType) as string, }; } else { tunnelLogger.warn("No endpoint credentials found in database", { @@ -605,7 +617,6 @@ async function connectSSHTunnel( credentialId: tunnelConfig.endpointCredentialId, }); } - } else { } } catch (error) { tunnelLogger.warn( @@ -631,7 +642,9 @@ async function connectSSHTunnel( try { conn.end(); - } catch (e) {} + } catch { + // Ignore errors + } activeTunnels.delete(tunnelName); @@ -771,7 +784,9 @@ async function connectSSHTunnel( const verification = tunnelVerifications.get(tunnelName); if (verification?.timeout) clearTimeout(verification.timeout); verification?.conn.end(); - } catch (e) {} + } catch { + // Ignore errors + } tunnelVerifications.delete(tunnelName); } @@ -822,13 +837,13 @@ async function connectSSHTunnel( } }); - stream.stdout?.on("data", (data: Buffer) => { - const output = data.toString().trim(); - if (output) { - } + stream.stdout?.on("data", () => { + // Silently consume stdout data }); - stream.on("error", (err: Error) => {}); + stream.on("error", () => { + // Silently consume stream errors + }); stream.stderr.on("data", (data) => { const errorMsg = data.toString().trim(); @@ -888,7 +903,7 @@ async function connectSSHTunnel( }); }); - const connOptions: any = { + const connOptions: Record = { host: tunnelConfig.sourceIP, port: tunnelConfig.sourceSSHPort, username: tunnelConfig.sourceUsername, @@ -1026,15 +1041,19 @@ async function killRemoteTunnelByMarker( if (credentials.length > 0) { const credential = credentials[0]; resolvedSourceCredentials = { - password: credential.password, - sshKey: - credential.private_key || credential.privateKey || credential.key, - keyPassword: credential.key_password || credential.keyPassword, - keyType: credential.key_type || credential.keyType, - authMethod: credential.auth_type || credential.authType, + password: credential.password as string | undefined, + sshKey: (credential.private_key || + credential.privateKey || + credential.key) as string | undefined, + keyPassword: (credential.key_password || credential.keyPassword) as + | string + | undefined, + keyType: (credential.key_type || credential.keyType) as + | string + | undefined, + authMethod: (credential.auth_type || credential.authType) as string, }; } - } else { } } catch (error) { tunnelLogger.warn("Failed to resolve source credentials for cleanup", { @@ -1046,7 +1065,7 @@ async function killRemoteTunnelByMarker( } const conn = new Client(); - const connOptions: any = { + const connOptions: Record = { host: tunnelConfig.sourceIP, port: tunnelConfig.sourceSSHPort, username: tunnelConfig.sourceUsername, @@ -1122,7 +1141,7 @@ async function killRemoteTunnelByMarker( conn.on("ready", () => { const checkCmd = `ps aux | grep -E '(${tunnelMarker}|ssh.*-R.*${tunnelConfig.endpointPort}:localhost:${tunnelConfig.sourcePort}.*${tunnelConfig.endpointUsername}@${tunnelConfig.endpointIP}|sshpass.*ssh.*-R.*${tunnelConfig.endpointPort})' | grep -v grep`; - conn.exec(checkCmd, (err, stream) => { + conn.exec(checkCmd, (_err, stream) => { let foundProcesses = false; stream.on("data", (data) => { @@ -1150,7 +1169,7 @@ async function killRemoteTunnelByMarker( function executeNextKillCommand() { if (commandIndex >= killCmds.length) { - conn.exec(checkCmd, (err, verifyStream) => { + conn.exec(checkCmd, (_err, verifyStream) => { let stillRunning = false; verifyStream.on("data", (data) => { @@ -1183,18 +1202,15 @@ async function killRemoteTunnelByMarker( tunnelLogger.warn( `Kill command ${commandIndex + 1} failed for '${tunnelName}': ${err.message}`, ); - } else { } - stream.on("close", (code) => { + stream.on("close", () => { commandIndex++; executeNextKillCommand(); }); - stream.on("data", (data) => { - const output = data.toString().trim(); - if (output) { - } + stream.on("data", () => { + // Silently consume stream data }); stream.stderr.on("data", (data) => { @@ -1423,14 +1439,6 @@ async function initializeAutoStartTunnels(): Promise { isPinned: host.pin, }; - const hasSourcePassword = host.autostartPassword; - const hasSourceKey = host.autostartKey; - const hasEndpointPassword = - tunnelConnection.endpointPassword || - endpointHost.autostartPassword; - const hasEndpointKey = - tunnelConnection.endpointKey || endpointHost.autostartKey; - autoStartTunnels.push(tunnelConfig); } else { tunnelLogger.error( @@ -1453,10 +1461,10 @@ async function initializeAutoStartTunnels(): Promise { }); }, 1000); } - } catch (error: any) { + } catch (error) { tunnelLogger.error( "Failed to initialize auto-start tunnels:", - error.message, + error instanceof Error ? error.message : "Unknown error", ); } } diff --git a/src/backend/starter.ts b/src/backend/starter.ts index fb0cfc89..ad8b3120 100644 --- a/src/backend/starter.ts +++ b/src/backend/starter.ts @@ -21,7 +21,9 @@ import { systemLogger, versionLogger } from "./utils/logger.js"; if (persistentConfig.parsed) { Object.assign(process.env, persistentConfig.parsed); } - } catch {} + } catch { + // Ignore errors if .env file doesn't exist + } let version = "unknown"; @@ -73,7 +75,7 @@ import { systemLogger, versionLogger } from "./utils/logger.js"; version = foundVersion; break; } - } catch (error) { + } catch { continue; } } @@ -102,6 +104,7 @@ import { systemLogger, versionLogger } from "./utils/logger.js"; await import("./ssh/tunnel.js"); await import("./ssh/file-manager.js"); await import("./ssh/server-stats.js"); + await import("./homepage.js"); process.on("SIGINT", () => { systemLogger.info( @@ -126,7 +129,7 @@ import { systemLogger, versionLogger } from "./utils/logger.js"; process.exit(1); }); - process.on("unhandledRejection", (reason, promise) => { + process.on("unhandledRejection", (reason) => { systemLogger.error("Unhandled promise rejection", reason, { operation: "error_handling", }); diff --git a/src/backend/utils/auth-manager.ts b/src/backend/utils/auth-manager.ts index a13db6cd..5a1b3263 100644 --- a/src/backend/utils/auth-manager.ts +++ b/src/backend/utils/auth-manager.ts @@ -23,6 +23,18 @@ interface JWTPayload { exp?: number; } +interface AuthenticatedRequest extends Request { + userId?: string; + pendingTOTP?: boolean; + dataKey?: Buffer; +} + +interface RequestWithHeaders extends Request { + headers: Request["headers"] & { + "x-forwarded-proto"?: string; + }; +} + class AuthManager { private static instance: AuthManager; private systemCrypto: SystemCrypto; @@ -108,7 +120,6 @@ class AuthManager { if (migrationResult.migrated) { await saveMemoryDatabaseToFile(); - } else { } } catch (error) { databaseLogger.error("Lazy encryption migration failed", error, { @@ -164,7 +175,10 @@ class AuthManager { }); } - getSecureCookieOptions(req: any, maxAge: number = 24 * 60 * 60 * 1000) { + getSecureCookieOptions( + req: RequestWithHeaders, + maxAge: number = 24 * 60 * 60 * 1000, + ) { return { httpOnly: false, secure: req.secure || req.headers["x-forwarded-proto"] === "https", @@ -176,10 +190,11 @@ class AuthManager { createAuthMiddleware() { return async (req: Request, res: Response, next: NextFunction) => { - let token = req.cookies?.jwt; + const authReq = req as AuthenticatedRequest; + let token = authReq.cookies?.jwt; if (!token) { - const authHeader = req.headers["authorization"]; + const authHeader = authReq.headers["authorization"]; if (authHeader?.startsWith("Bearer ")) { token = authHeader.split(" ")[1]; } @@ -195,15 +210,16 @@ class AuthManager { return res.status(401).json({ error: "Invalid token" }); } - (req as any).userId = payload.userId; - (req as any).pendingTOTP = payload.pendingTOTP; + authReq.userId = payload.userId; + authReq.pendingTOTP = payload.pendingTOTP; next(); }; } createDataAccessMiddleware() { return async (req: Request, res: Response, next: NextFunction) => { - const userId = (req as any).userId; + const authReq = req as AuthenticatedRequest; + const userId = authReq.userId; if (!userId) { return res.status(401).json({ error: "Authentication required" }); } @@ -216,19 +232,26 @@ class AuthManager { }); } - (req as any).dataKey = dataKey; + authReq.dataKey = dataKey; next(); }; } createAdminMiddleware() { return async (req: Request, res: Response, next: NextFunction) => { - const authHeader = req.headers["authorization"]; - if (!authHeader?.startsWith("Bearer ")) { - return res.status(401).json({ error: "Missing Authorization header" }); + let token = req.cookies?.jwt; + + if (!token) { + const authHeader = req.headers["authorization"]; + if (authHeader?.startsWith("Bearer ")) { + token = authHeader.split(" ")[1]; + } + } + + if (!token) { + return res.status(401).json({ error: "Missing authentication token" }); } - const token = authHeader.split(" ")[1]; const payload = await this.verifyJWTToken(token); if (!payload) { @@ -257,8 +280,9 @@ class AuthManager { return res.status(403).json({ error: "Admin access required" }); } - (req as any).userId = payload.userId; - (req as any).pendingTOTP = payload.pendingTOTP; + const authReq = req as AuthenticatedRequest; + authReq.userId = payload.userId; + authReq.pendingTOTP = payload.pendingTOTP; next(); } catch (error) { databaseLogger.error("Failed to verify admin privileges", error, { diff --git a/src/backend/utils/auto-ssl-setup.ts b/src/backend/utils/auto-ssl-setup.ts index e2d1034a..b5bb01ed 100644 --- a/src/backend/utils/auto-ssl-setup.ts +++ b/src/backend/utils/auto-ssl-setup.ts @@ -1,7 +1,6 @@ import { execSync } from "child_process"; import { promises as fs } from "fs"; import path from "path"; -import crypto from "crypto"; import { systemLogger } from "./logger.js"; export class AutoSSLSetup { @@ -102,7 +101,7 @@ export class AutoSSLSetup { try { try { execSync("openssl version", { stdio: "pipe" }); - } catch (error) { + } catch { throw new Error( "OpenSSL is not installed or not available in PATH. Please install OpenSSL to enable SSL certificate generation.", ); @@ -234,7 +233,9 @@ IP.3 = 0.0.0.0 let envContent = ""; try { envContent = await fs.readFile(this.ENV_FILE, "utf8"); - } catch {} + } catch { + // File doesn't exist yet, will create with SSL config + } let updatedContent = envContent; let hasChanges = false; diff --git a/src/backend/utils/data-crypto.ts b/src/backend/utils/data-crypto.ts index 870d0d5f..6761cc5b 100644 --- a/src/backend/utils/data-crypto.ts +++ b/src/backend/utils/data-crypto.ts @@ -3,6 +3,19 @@ import { LazyFieldEncryption } from "./lazy-field-encryption.js"; import { UserCrypto } from "./user-crypto.js"; import { databaseLogger } from "./logger.js"; +interface DatabaseInstance { + prepare: (sql: string) => { + all: (param?: unknown) => DatabaseRecord[]; + get: (param?: unknown) => DatabaseRecord; + run: (...params: unknown[]) => unknown; + }; +} + +interface DatabaseRecord { + id: number | string; + [key: string]: unknown; +} + class DataCrypto { private static userCrypto: UserCrypto; @@ -10,13 +23,13 @@ class DataCrypto { this.userCrypto = UserCrypto.getInstance(); } - static encryptRecord( + static encryptRecord>( tableName: string, - record: any, + record: T, userId: string, userDataKey: Buffer, - ): any { - const encryptedRecord = { ...record }; + ): T { + const encryptedRecord: Record = { ...record }; const recordId = record.id || "temp-" + Date.now(); for (const [fieldName, value] of Object.entries(record)) { @@ -24,24 +37,24 @@ class DataCrypto { encryptedRecord[fieldName] = FieldCrypto.encryptField( value as string, userDataKey, - recordId, + recordId as string, fieldName, ); } } - return encryptedRecord; + return encryptedRecord as T; } - static decryptRecord( + static decryptRecord>( tableName: string, - record: any, + record: T, userId: string, userDataKey: Buffer, - ): any { + ): T { if (!record) return record; - const decryptedRecord = { ...record }; + const decryptedRecord: Record = { ...record }; const recordId = record.id; for (const [fieldName, value] of Object.entries(record)) { @@ -49,21 +62,21 @@ class DataCrypto { decryptedRecord[fieldName] = LazyFieldEncryption.safeGetFieldValue( value as string, userDataKey, - recordId, + recordId as string, fieldName, ); } } - return decryptedRecord; + return decryptedRecord as T; } - static decryptRecords( + static decryptRecords>( tableName: string, - records: any[], + records: T[], userId: string, userDataKey: Buffer, - ): any[] { + ): T[] { if (!Array.isArray(records)) return records; return records.map((record) => this.decryptRecord(tableName, record, userId, userDataKey), @@ -73,7 +86,7 @@ class DataCrypto { static async migrateUserSensitiveFields( userId: string, userDataKey: Buffer, - db: any, + db: DatabaseInstance, ): Promise<{ migrated: boolean; migratedTables: string[]; @@ -84,7 +97,7 @@ class DataCrypto { let migratedFieldsCount = 0; try { - const { needsMigration, plaintextFields } = + const { needsMigration } = await LazyFieldEncryption.checkUserNeedsMigration( userId, userDataKey, @@ -97,7 +110,7 @@ class DataCrypto { const sshDataRecords = db .prepare("SELECT * FROM ssh_data WHERE user_id = ?") - .all(userId); + .all(userId) as DatabaseRecord[]; for (const record of sshDataRecords) { const sensitiveFields = LazyFieldEncryption.getSensitiveFieldsForTable("ssh_data"); @@ -132,7 +145,7 @@ class DataCrypto { const sshCredentialsRecords = db .prepare("SELECT * FROM ssh_credentials WHERE user_id = ?") - .all(userId); + .all(userId) as DatabaseRecord[]; for (const record of sshCredentialsRecords) { const sensitiveFields = LazyFieldEncryption.getSensitiveFieldsForTable("ssh_credentials"); @@ -169,7 +182,7 @@ class DataCrypto { const userRecord = db .prepare("SELECT * FROM users WHERE id = ?") - .get(userId); + .get(userId) as DatabaseRecord | undefined; if (userRecord) { const sensitiveFields = LazyFieldEncryption.getSensitiveFieldsForTable("users"); @@ -220,7 +233,7 @@ class DataCrypto { static async reencryptUserDataAfterPasswordReset( userId: string, newUserDataKey: Buffer, - db: any, + db: DatabaseInstance, ): Promise<{ success: boolean; reencryptedTables: string[]; @@ -262,17 +275,21 @@ class DataCrypto { try { const records = db .prepare(`SELECT * FROM ${table} WHERE user_id = ?`) - .all(userId); + .all(userId) as DatabaseRecord[]; for (const record of records) { const recordId = record.id.toString(); + const updatedRecord: DatabaseRecord = { ...record }; let needsUpdate = false; - const updatedRecord = { ...record }; for (const fieldName of fields) { const fieldValue = record[fieldName]; - if (fieldValue && fieldValue.trim() !== "") { + if ( + fieldValue && + typeof fieldValue === "string" && + fieldValue.trim() !== "" + ) { try { const reencryptedValue = FieldCrypto.encryptField( fieldValue, @@ -384,29 +401,29 @@ class DataCrypto { return userDataKey; } - static encryptRecordForUser( + static encryptRecordForUser>( tableName: string, - record: any, + record: T, userId: string, - ): any { + ): T { const userDataKey = this.validateUserAccess(userId); return this.encryptRecord(tableName, record, userId, userDataKey); } - static decryptRecordForUser( + static decryptRecordForUser>( tableName: string, - record: any, + record: T, userId: string, - ): any { + ): T { const userDataKey = this.validateUserAccess(userId); return this.decryptRecord(tableName, record, userId, userDataKey); } - static decryptRecordsForUser( + static decryptRecordsForUser>( tableName: string, - records: any[], + records: T[], userId: string, - ): any[] { + ): T[] { const userDataKey = this.validateUserAccess(userId); return this.decryptRecords(tableName, records, userId, userDataKey); } @@ -435,7 +452,7 @@ class DataCrypto { ); return decrypted === testData; - } catch (error) { + } catch { return false; } } diff --git a/src/backend/utils/database-file-encryption.ts b/src/backend/utils/database-file-encryption.ts index db302d2e..002464b0 100644 --- a/src/backend/utils/database-file-encryption.ts +++ b/src/backend/utils/database-file-encryption.ts @@ -30,7 +30,11 @@ class DatabaseFileEncryption { const iv = crypto.randomBytes(16); - const cipher = crypto.createCipheriv(this.ALGORITHM, key, iv) as any; + const cipher = crypto.createCipheriv( + this.ALGORITHM, + key, + iv, + ) as crypto.CipherGCM; const encrypted = Buffer.concat([cipher.update(buffer), cipher.final()]); const tag = cipher.getAuthTag(); @@ -78,7 +82,11 @@ class DatabaseFileEncryption { const iv = crypto.randomBytes(16); - const cipher = crypto.createCipheriv(this.ALGORITHM, key, iv) as any; + const cipher = crypto.createCipheriv( + this.ALGORITHM, + key, + iv, + ) as crypto.CipherGCM; const encrypted = Buffer.concat([ cipher.update(sourceData), cipher.final(), @@ -163,7 +171,7 @@ class DatabaseFileEncryption { metadata.algorithm, key, Buffer.from(metadata.iv, "hex"), - ) as any; + ) as crypto.DecipherGCM; decipher.setAuthTag(Buffer.from(metadata.tag, "hex")); const decryptedBuffer = Buffer.concat([ @@ -233,7 +241,7 @@ class DatabaseFileEncryption { metadata.algorithm, key, Buffer.from(metadata.iv, "hex"), - ) as any; + ) as crypto.DecipherGCM; decipher.setAuthTag(Buffer.from(metadata.tag, "hex")); const decrypted = Buffer.concat([ @@ -301,7 +309,6 @@ class DatabaseFileEncryption { const metadata: EncryptedFileMetadata = JSON.parse(metadataContent); const fileStats = fs.statSync(encryptedPath); - const currentFingerprint = "termix-v1-file"; return { version: metadata.version, diff --git a/src/backend/utils/database-migration.ts b/src/backend/utils/database-migration.ts index ebf3192b..153ef18d 100644 --- a/src/backend/utils/database-migration.ts +++ b/src/backend/utils/database-migration.ts @@ -55,7 +55,6 @@ export class DatabaseMigration { if (hasEncryptedDb && hasUnencryptedDb) { const unencryptedSize = fs.statSync(this.unencryptedDbPath).size; - const encryptedSize = fs.statSync(this.encryptedDbPath).size; if (unencryptedSize === 0) { needsMigration = false; @@ -168,9 +167,6 @@ export class DatabaseMigration { return false; } - let totalOriginalRows = 0; - let totalMemoryRows = 0; - for (const table of originalTables) { const originalCount = originalDb .prepare(`SELECT COUNT(*) as count FROM ${table.name}`) @@ -179,9 +175,6 @@ export class DatabaseMigration { .prepare(`SELECT COUNT(*) as count FROM ${table.name}`) .get() as { count: number }; - totalOriginalRows += originalCount.count; - totalMemoryRows += memoryCount.count; - if (originalCount.count !== memoryCount.count) { databaseLogger.error( "Row count mismatch for table during migration verification", @@ -241,7 +234,9 @@ export class DatabaseMigration { memoryDb.exec("PRAGMA foreign_keys = OFF"); for (const table of tables) { - const rows = originalDb.prepare(`SELECT * FROM ${table.name}`).all(); + const rows = originalDb + .prepare(`SELECT * FROM ${table.name}`) + .all() as Record[]; if (rows.length > 0) { const columns = Object.keys(rows[0]); @@ -251,7 +246,7 @@ export class DatabaseMigration { ); const insertTransaction = memoryDb.transaction( - (dataRows: any[]) => { + (dataRows: Record[]) => { for (const row of dataRows) { const values = columns.map((col) => row[col]); insertStmt.run(values); diff --git a/src/backend/utils/field-crypto.ts b/src/backend/utils/field-crypto.ts index 098b5b8e..78221220 100644 --- a/src/backend/utils/field-crypto.ts +++ b/src/backend/utils/field-crypto.ts @@ -21,8 +21,9 @@ class FieldCrypto { "totp_secret", "totp_backup_codes", "oidc_identifier", + "oidcIdentifier", ]), - ssh_data: new Set(["password", "key", "key_password"]), + ssh_data: new Set(["password", "key", "key_password", "keyPassword"]), ssh_credentials: new Set([ "password", "private_key", @@ -47,7 +48,11 @@ class FieldCrypto { ); const iv = crypto.randomBytes(this.IV_LENGTH); - const cipher = crypto.createCipheriv(this.ALGORITHM, fieldKey, iv) as any; + const cipher = crypto.createCipheriv( + this.ALGORITHM, + fieldKey, + iv, + ) as crypto.CipherGCM; let encrypted = cipher.update(plaintext, "utf8", "hex"); encrypted += cipher.final("hex"); @@ -89,7 +94,7 @@ class FieldCrypto { this.ALGORITHM, fieldKey, Buffer.from(encrypted.iv, "hex"), - ) as any; + ) as crypto.DecipherGCM; decipher.setAuthTag(Buffer.from(encrypted.tag, "hex")); let decrypted = decipher.update(encrypted.data, "hex", "utf8"); diff --git a/src/backend/utils/lazy-field-encryption.ts b/src/backend/utils/lazy-field-encryption.ts index efe5ea75..e64db2a3 100644 --- a/src/backend/utils/lazy-field-encryption.ts +++ b/src/backend/utils/lazy-field-encryption.ts @@ -1,6 +1,14 @@ import { FieldCrypto } from "./field-crypto.js"; import { databaseLogger } from "./logger.js"; +interface DatabaseInstance { + prepare: (sql: string) => { + all: (param?: unknown) => unknown[]; + get: (param?: unknown) => unknown; + run: (...params: unknown[]) => unknown; + }; +} + export class LazyFieldEncryption { private static readonly LEGACY_FIELD_NAME_MAP: Record = { key_password: "keyPassword", @@ -39,7 +47,7 @@ export class LazyFieldEncryption { return false; } return true; - } catch (jsonError) { + } catch { return true; } } @@ -74,7 +82,9 @@ export class LazyFieldEncryption { legacyFieldName, ); return decrypted; - } catch (legacyError) {} + } catch { + // Ignore legacy format errors + } } const sensitiveFields = [ @@ -145,7 +155,7 @@ export class LazyFieldEncryption { wasPlaintext: false, wasLegacyEncryption: false, }; - } catch (error) { + } catch { const legacyFieldName = this.LEGACY_FIELD_NAME_MAP[fieldName]; if (legacyFieldName) { try { @@ -166,7 +176,9 @@ export class LazyFieldEncryption { wasPlaintext: false, wasLegacyEncryption: true, }; - } catch (legacyError) {} + } catch { + // Ignore legacy format errors + } } return { encrypted: fieldValue, @@ -178,12 +190,12 @@ export class LazyFieldEncryption { } static migrateRecordSensitiveFields( - record: any, + record: Record, sensitiveFields: string[], userKEK: Buffer, recordId: string, ): { - updatedRecord: any; + updatedRecord: Record; migratedFields: string[]; needsUpdate: boolean; } { @@ -198,7 +210,7 @@ export class LazyFieldEncryption { try { const { encrypted, wasPlaintext, wasLegacyEncryption } = this.migrateFieldToEncrypted( - fieldValue, + fieldValue as string, userKEK, recordId, fieldName, @@ -253,7 +265,7 @@ export class LazyFieldEncryption { try { FieldCrypto.decryptField(fieldValue, userKEK, recordId, fieldName); return false; - } catch (error) { + } catch { const legacyFieldName = this.LEGACY_FIELD_NAME_MAP[fieldName]; if (legacyFieldName) { try { @@ -264,7 +276,7 @@ export class LazyFieldEncryption { legacyFieldName, ); return true; - } catch (legacyError) { + } catch { return false; } } @@ -275,7 +287,7 @@ export class LazyFieldEncryption { static async checkUserNeedsMigration( userId: string, userKEK: Buffer, - db: any, + db: DatabaseInstance, ): Promise<{ needsMigration: boolean; plaintextFields: Array<{ @@ -294,7 +306,9 @@ export class LazyFieldEncryption { try { const sshHosts = db .prepare("SELECT * FROM ssh_data WHERE user_id = ?") - .all(userId); + .all(userId) as Array< + Record & { id: string | number } + >; for (const host of sshHosts) { const sensitiveFields = this.getSensitiveFieldsForTable("ssh_data"); const hostPlaintextFields: string[] = []; @@ -303,7 +317,7 @@ export class LazyFieldEncryption { if ( host[field] && this.fieldNeedsMigration( - host[field], + host[field] as string, userKEK, host.id.toString(), field, @@ -325,7 +339,9 @@ export class LazyFieldEncryption { const sshCredentials = db .prepare("SELECT * FROM ssh_credentials WHERE user_id = ?") - .all(userId); + .all(userId) as Array< + Record & { id: string | number } + >; for (const credential of sshCredentials) { const sensitiveFields = this.getSensitiveFieldsForTable("ssh_credentials"); @@ -335,7 +351,7 @@ export class LazyFieldEncryption { if ( credential[field] && this.fieldNeedsMigration( - credential[field], + credential[field] as string, userKEK, credential.id.toString(), field, diff --git a/src/backend/utils/logger.ts b/src/backend/utils/logger.ts index f020047a..3f986399 100644 --- a/src/backend/utils/logger.ts +++ b/src/backend/utils/logger.ts @@ -11,7 +11,7 @@ export interface LogContext { sessionId?: string; requestId?: string; duration?: number; - [key: string]: any; + [key: string]: unknown; } const SENSITIVE_FIELDS = [ @@ -253,5 +253,6 @@ export const apiLogger = new Logger("API", "🌐", "#3b82f6"); export const authLogger = new Logger("AUTH", "🔐", "#ef4444"); export const systemLogger = new Logger("SYSTEM", "🚀", "#14b8a6"); export const versionLogger = new Logger("VERSION", "📦", "#8b5cf6"); +export const homepageLogger = new Logger("HOMEPAGE", "🏠", "#ec4899"); export const logger = systemLogger; diff --git a/src/backend/utils/simple-db-ops.ts b/src/backend/utils/simple-db-ops.ts index c324e0a2..e2764dca 100644 --- a/src/backend/utils/simple-db-ops.ts +++ b/src/backend/utils/simple-db-ops.ts @@ -2,10 +2,11 @@ import { getDb, DatabaseSaveTrigger } from "../database/db/index.js"; import { DataCrypto } from "./data-crypto.js"; import type { SQLiteTable } from "drizzle-orm/sqlite-core"; -type TableName = "users" | "ssh_data" | "ssh_credentials"; +type TableName = "users" | "ssh_data" | "ssh_credentials" | "recent_activity"; class SimpleDBOps { - static async insert>( + static async insert>( + // eslint-disable-next-line @typescript-eslint/no-explicit-any table: SQLiteTable, tableName: TableName, data: T, @@ -44,8 +45,8 @@ class SimpleDBOps { return decryptedResult as T; } - static async select>( - query: any, + static async select>( + query: unknown, tableName: TableName, userId: string, ): Promise { @@ -56,9 +57,9 @@ class SimpleDBOps { const results = await query; - const decryptedResults = DataCrypto.decryptRecords( + const decryptedResults = DataCrypto.decryptRecords( tableName, - results, + results as T[], userId, userDataKey, ); @@ -66,8 +67,8 @@ class SimpleDBOps { return decryptedResults; } - static async selectOne>( - query: any, + static async selectOne>( + query: unknown, tableName: TableName, userId: string, ): Promise { @@ -79,9 +80,9 @@ class SimpleDBOps { const result = await query; if (!result) return undefined; - const decryptedResult = DataCrypto.decryptRecord( + const decryptedResult = DataCrypto.decryptRecord( tableName, - result, + result as T, userId, userDataKey, ); @@ -89,10 +90,11 @@ class SimpleDBOps { return decryptedResult; } - static async update>( + static async update>( + // eslint-disable-next-line @typescript-eslint/no-explicit-any table: SQLiteTable, tableName: TableName, - where: any, + where: unknown, data: Partial, userId: string, ): Promise { @@ -108,7 +110,8 @@ class SimpleDBOps { const result = await getDb() .update(table) .set(encryptedData) - .where(where) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .where(where as any) .returning(); DatabaseSaveTrigger.triggerSave(`update_${tableName}`); @@ -124,12 +127,16 @@ class SimpleDBOps { } static async delete( + // eslint-disable-next-line @typescript-eslint/no-explicit-any table: SQLiteTable, tableName: TableName, - where: any, - userId: string, - ): Promise { - const result = await getDb().delete(table).where(where).returning(); + where: unknown, + ): Promise { + const result = await getDb() + .delete(table) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .where(where as any) + .returning(); DatabaseSaveTrigger.triggerSave(`delete_${tableName}`); @@ -144,13 +151,10 @@ class SimpleDBOps { return DataCrypto.getUserDataKey(userId) !== null; } - static async selectEncrypted( - query: any, - tableName: TableName, - ): Promise { + static async selectEncrypted(query: unknown): Promise { const results = await query; - return results; + return results as unknown[]; } } diff --git a/src/backend/utils/ssh-key-utils.ts b/src/backend/utils/ssh-key-utils.ts index b19f95c9..2ef8c2e5 100644 --- a/src/backend/utils/ssh-key-utils.ts +++ b/src/backend/utils/ssh-key-utils.ts @@ -49,7 +49,7 @@ function detectKeyTypeFromContent(keyContent: string): string { } return "ssh-rsa"; - } catch (error) { + } catch { return "ssh-rsa"; } } @@ -84,7 +84,9 @@ function detectKeyTypeFromContent(keyContent: string): string { } else if (decodedString.includes("1.3.101.112")) { return "ssh-ed25519"; } - } catch (error) {} + } catch { + // Cannot decode key, fallback to length-based detection + } if (content.length < 800) { return "ssh-ed25519"; @@ -140,7 +142,9 @@ function detectPublicKeyTypeFromContent(publicKeyContent: string): string { } else if (decodedString.includes("1.3.101.112")) { return "ssh-ed25519"; } - } catch (error) {} + } catch { + // Cannot decode key, fallback to length-based detection + } if (content.length < 400) { return "ssh-ed25519"; @@ -236,13 +240,15 @@ export function parseSSHKey( } else { publicKey = ""; } - } catch (error) { + } catch { publicKey = ""; } useSSH2 = true; } - } catch (error) {} + } catch { + // SSH2 parsing failed, will use fallback method + } } if (!useSSH2) { @@ -268,7 +274,9 @@ export function parseSSHKey( success: true, }; } - } catch (fallbackError) {} + } catch { + // Fallback parsing also failed + } return { privateKey: privateKeyData, @@ -310,7 +318,7 @@ export function detectKeyType(privateKeyData: string): string { return "unknown"; } return parsedKey.type || "unknown"; - } catch (error) { + } catch { return "unknown"; } } diff --git a/src/backend/utils/system-crypto.ts b/src/backend/utils/system-crypto.ts index cd805bfc..9f9c15b0 100644 --- a/src/backend/utils/system-crypto.ts +++ b/src/backend/utils/system-crypto.ts @@ -37,7 +37,9 @@ class SystemCrypto { process.env.JWT_SECRET = jwtMatch[1]; return; } - } catch {} + } catch { + // Ignore file read errors, will generate new secret + } await this.generateAndGuideUser(); } catch (error) { @@ -74,7 +76,9 @@ class SystemCrypto { process.env.DATABASE_KEY = dbKeyMatch[1]; return; } - } catch {} + } catch { + // Ignore file read errors, will generate new key + } await this.generateAndGuideDatabaseKey(); } catch (error) { @@ -111,7 +115,9 @@ class SystemCrypto { process.env.INTERNAL_AUTH_TOKEN = tokenMatch[1]; return; } - } catch {} + } catch { + // Ignore file read errors, will generate new token + } await this.generateAndGuideInternalAuthToken(); } catch (error) { diff --git a/src/backend/utils/user-crypto.ts b/src/backend/utils/user-crypto.ts index 4bf40338..607066b6 100644 --- a/src/backend/utils/user-crypto.ts +++ b/src/backend/utils/user-crypto.ts @@ -163,9 +163,10 @@ class UserCrypto { async authenticateOIDCUser(userId: string): Promise { try { + const kekSalt = await this.getKEKSalt(userId); const encryptedDEK = await this.getEncryptedDEK(userId); - if (!encryptedDEK) { + if (!kekSalt || !encryptedDEK) { await this.setupOIDCUserEncryption(userId); return true; } @@ -195,7 +196,7 @@ class UserCrypto { DEK.fill(0); return true; - } catch (error) { + } catch { await this.setupOIDCUserEncryption(userId); return true; } @@ -276,21 +277,6 @@ class UserCrypto { oldKEK.fill(0); newKEK.fill(0); - - const dekCopy = Buffer.from(DEK); - - const now = Date.now(); - const oldSession = this.userSessions.get(userId); - if (oldSession) { - oldSession.dataKey.fill(0); - } - - this.userSessions.set(userId, { - dataKey: dekCopy, - lastActivity: now, - expiresAt: now + UserCrypto.SESSION_DURATION, - }); - DEK.fill(0); return true; @@ -363,7 +349,7 @@ class UserCrypto { DEK.fill(0); return true; - } catch (error) { + } catch { return false; } } @@ -482,7 +468,7 @@ class UserCrypto { } return JSON.parse(result[0].value); - } catch (error) { + } catch { return null; } } @@ -522,7 +508,7 @@ class UserCrypto { } return JSON.parse(result[0].value); - } catch (error) { + } catch { return null; } } diff --git a/src/backend/utils/user-data-export.ts b/src/backend/utils/user-data-export.ts index 82d3fde3..03c3fff3 100644 --- a/src/backend/utils/user-data-export.ts +++ b/src/backend/utils/user-data-export.ts @@ -18,14 +18,14 @@ interface UserExportData { userId: string; username: string; userData: { - sshHosts: any[]; - sshCredentials: any[]; + sshHosts: unknown[]; + sshCredentials: unknown[]; fileManagerData: { - recent: any[]; - pinned: any[]; - shortcuts: any[]; + recent: unknown[]; + pinned: unknown[]; + shortcuts: unknown[]; }; - dismissedAlerts: any[]; + dismissedAlerts: unknown[]; }; metadata: { totalRecords: number; @@ -83,7 +83,7 @@ class UserDataExport { ) : sshHosts; - let sshCredentialsData: any[] = []; + let sshCredentialsData: unknown[] = []; if (includeCredentials) { const credentials = await getDb() .select() @@ -185,7 +185,10 @@ class UserDataExport { return JSON.stringify(exportData, null, pretty ? 2 : 0); } - static validateExportData(data: any): { valid: boolean; errors: string[] } { + static validateExportData(data: unknown): { + valid: boolean; + errors: string[]; + } { const errors: string[] = []; if (!data || typeof data !== "object") { @@ -193,23 +196,26 @@ class UserDataExport { return { valid: false, errors }; } - if (!data.version) { + const dataObj = data as Record; + + if (!dataObj.version) { errors.push("Missing version field"); } - if (!data.userId) { + if (!dataObj.userId) { errors.push("Missing userId field"); } - if (!data.userData || typeof data.userData !== "object") { + if (!dataObj.userData || typeof dataObj.userData !== "object") { errors.push("Missing or invalid userData field"); } - if (!data.metadata || typeof data.metadata !== "object") { + if (!dataObj.metadata || typeof dataObj.metadata !== "object") { errors.push("Missing or invalid metadata field"); } - if (data.userData) { + if (dataObj.userData) { + const userData = dataObj.userData as Record; const requiredFields = [ "sshHosts", "sshCredentials", @@ -218,23 +224,24 @@ class UserDataExport { ]; for (const field of requiredFields) { if ( - !Array.isArray(data.userData[field]) && - !( - field === "fileManagerData" && - typeof data.userData[field] === "object" - ) + !Array.isArray(userData[field]) && + !(field === "fileManagerData" && typeof userData[field] === "object") ) { errors.push(`Missing or invalid userData.${field} field`); } } if ( - data.userData.fileManagerData && - typeof data.userData.fileManagerData === "object" + userData.fileManagerData && + typeof userData.fileManagerData === "object" ) { + const fileManagerData = userData.fileManagerData as Record< + string, + unknown + >; const fmFields = ["recent", "pinned", "shortcuts"]; for (const field of fmFields) { - if (!Array.isArray(data.userData.fileManagerData[field])) { + if (!Array.isArray(fileManagerData[field])) { errors.push( `Missing or invalid userData.fileManagerData.${field} field`, ); diff --git a/src/backend/utils/user-data-import.ts b/src/backend/utils/user-data-import.ts index 448d3c00..da776893 100644 --- a/src/backend/utils/user-data-import.ts +++ b/src/backend/utils/user-data-import.ts @@ -12,7 +12,6 @@ import { eq, and } from "drizzle-orm"; import { DataCrypto } from "./data-crypto.js"; import { UserDataExport, type UserExportData } from "./user-data-export.js"; import { databaseLogger } from "./logger.js"; -import { nanoid } from "nanoid"; interface ImportOptions { replaceExisting?: boolean; @@ -90,7 +89,7 @@ class UserDataImport { ) { const importStats = await this.importSshHosts( targetUserId, - exportData.userData.sshHosts, + exportData.userData.sshHosts as Record[], { replaceExisting, dryRun, userDataKey }, ); result.summary.sshHostsImported = importStats.imported; @@ -105,7 +104,7 @@ class UserDataImport { ) { const importStats = await this.importSshCredentials( targetUserId, - exportData.userData.sshCredentials, + exportData.userData.sshCredentials as Record[], { replaceExisting, dryRun, userDataKey }, ); result.summary.sshCredentialsImported = importStats.imported; @@ -130,7 +129,7 @@ class UserDataImport { ) { const importStats = await this.importDismissedAlerts( targetUserId, - exportData.userData.dismissedAlerts, + exportData.userData.dismissedAlerts as Record[], { replaceExisting, dryRun }, ); result.summary.dismissedAlertsImported = importStats.imported; @@ -160,7 +159,7 @@ class UserDataImport { private static async importSshHosts( targetUserId: string, - sshHosts: any[], + sshHosts: Record[], options: { replaceExisting: boolean; dryRun: boolean; @@ -199,7 +198,9 @@ class UserDataImport { delete processedHostData.id; - await getDb().insert(sshData).values(processedHostData); + await getDb() + .insert(sshData) + .values(processedHostData as unknown as typeof sshData.$inferInsert); imported++; } catch (error) { errors.push( @@ -214,7 +215,7 @@ class UserDataImport { private static async importSshCredentials( targetUserId: string, - credentials: any[], + credentials: Record[], options: { replaceExisting: boolean; dryRun: boolean; @@ -255,7 +256,11 @@ class UserDataImport { delete processedCredentialData.id; - await getDb().insert(sshCredentials).values(processedCredentialData); + await getDb() + .insert(sshCredentials) + .values( + processedCredentialData as unknown as typeof sshCredentials.$inferInsert, + ); imported++; } catch (error) { errors.push( @@ -270,7 +275,7 @@ class UserDataImport { private static async importFileManagerData( targetUserId: string, - fileManagerData: any, + fileManagerData: Record, options: { replaceExisting: boolean; dryRun: boolean }, ) { let imported = 0; @@ -357,7 +362,7 @@ class UserDataImport { private static async importDismissedAlerts( targetUserId: string, - alerts: any[], + alerts: Record[], options: { replaceExisting: boolean; dryRun: boolean }, ) { let imported = 0; @@ -377,7 +382,7 @@ class UserDataImport { .where( and( eq(dismissedAlerts.userId, targetUserId), - eq(dismissedAlerts.alertId, alert.alertId), + eq(dismissedAlerts.alertId, alert.alertId as string), ), ); @@ -396,10 +401,12 @@ class UserDataImport { if (existing.length > 0 && options.replaceExisting) { await getDb() .update(dismissedAlerts) - .set(newAlert) + .set(newAlert as typeof dismissedAlerts.$inferInsert) .where(eq(dismissedAlerts.id, existing[0].id)); } else { - await getDb().insert(dismissedAlerts).values(newAlert); + await getDb() + .insert(dismissedAlerts) + .values(newAlert as typeof dismissedAlerts.$inferInsert); } imported++; diff --git a/src/components/theme-provider.tsx b/src/components/theme-provider.tsx index e18440d7..93e2f18c 100644 --- a/src/components/theme-provider.tsx +++ b/src/components/theme-provider.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import { createContext, useContext, useEffect, useState } from "react"; type Theme = "dark" | "light" | "system"; diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx index 46f988c2..b99be47d 100644 --- a/src/components/ui/badge.tsx +++ b/src/components/ui/badge.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 8b2e9e72..26ee717b 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { cva, type VariantProps } from "class-variance-authority"; diff --git a/src/components/ui/chart.tsx b/src/components/ui/chart.tsx new file mode 100644 index 00000000..c0479b5a --- /dev/null +++ b/src/components/ui/chart.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; +import * as RechartsPrimitive from "recharts"; + +import { cn } from "@/lib/utils"; + +// Chart Container +const ChartContainer = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + return ( +
+ ); +}); +ChartContainer.displayName = "ChartContainer"; + +export { ChartContainer, RechartsPrimitive }; diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx index 4ebbfe9c..50ee37c3 100644 --- a/src/components/ui/form.tsx +++ b/src/components/ui/form.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import * as React from "react"; import * as LabelPrimitive from "@radix-ui/react-label"; import { Slot } from "@radix-ui/react-slot"; diff --git a/src/components/ui/password-input.tsx b/src/components/ui/password-input.tsx index f1cd0066..5eac52b5 100644 --- a/src/components/ui/password-input.tsx +++ b/src/components/ui/password-input.tsx @@ -5,8 +5,7 @@ import { Eye, EyeOff } from "lucide-react"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; -interface PasswordInputProps - extends React.InputHTMLAttributes {} +type PasswordInputProps = React.InputHTMLAttributes; export const PasswordInput = React.forwardRef< HTMLInputElement, diff --git a/src/components/ui/shadcn-io/status/index.tsx b/src/components/ui/shadcn-io/status/index.tsx index 7139942b..5131e84c 100644 --- a/src/components/ui/shadcn-io/status/index.tsx +++ b/src/components/ui/shadcn-io/status/index.tsx @@ -17,10 +17,7 @@ export const Status = ({ className, status, ...props }: StatusProps) => ( export type StatusIndicatorProps = HTMLAttributes; -export const StatusIndicator = ({ - className, - ...props -}: StatusIndicatorProps) => ( +export const StatusIndicator = ({ ...props }: StatusIndicatorProps) => ( { const originalToast = toast; - const rateLimitedToast = (message: string, options?: any) => { + const rateLimitedToast = ( + message: string, + options?: Record, + ) => { const now = Date.now(); const lastToast = lastToastRef.current; @@ -25,13 +28,13 @@ const Toaster = ({ ...props }: ToasterProps) => { }; Object.assign(toast, { - success: (message: string, options?: any) => + success: (message: string, options?: Record) => rateLimitedToast(message, { ...options, type: "success" }), - error: (message: string, options?: any) => + error: (message: string, options?: Record) => rateLimitedToast(message, { ...options, type: "error" }), - warning: (message: string, options?: any) => + warning: (message: string, options?: Record) => rateLimitedToast(message, { ...options, type: "warning" }), - info: (message: string, options?: any) => + info: (message: string, options?: Record) => rateLimitedToast(message, { ...options, type: "info" }), message: rateLimitedToast, }); diff --git a/src/components/ui/textarea.tsx b/src/components/ui/textarea.tsx index e306ca0a..6c816b16 100644 --- a/src/components/ui/textarea.tsx +++ b/src/components/ui/textarea.tsx @@ -2,8 +2,7 @@ import * as React from "react"; import { cn } from "../../lib/utils"; -export interface TextareaProps - extends React.TextareaHTMLAttributes {} +export type TextareaProps = React.TextareaHTMLAttributes; const Textarea = React.forwardRef( ({ className, ...props }, ref) => { diff --git a/src/components/ui/version-check-modal.tsx b/src/components/ui/version-check-modal.tsx index 29d20aa9..52b10ddd 100644 --- a/src/components/ui/version-check-modal.tsx +++ b/src/components/ui/version-check-modal.tsx @@ -1,25 +1,25 @@ import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button.tsx"; import { VersionAlert } from "@/components/ui/version-alert.tsx"; -import { RefreshCw, X } from "lucide-react"; import { useTranslation } from "react-i18next"; import { checkElectronUpdate, isElectron } from "@/ui/main-axios.ts"; interface VersionCheckModalProps { - onDismiss: () => void; onContinue: () => void; isAuthenticated?: boolean; } export function VersionCheckModal({ - onDismiss, onContinue, isAuthenticated = false, }: VersionCheckModalProps) { const { t } = useTranslation(); - const [versionInfo, setVersionInfo] = useState(null); + const [versionInfo, setVersionInfo] = useState | null>(null); const [versionChecking, setVersionChecking] = useState(false); - const [versionDismissed, setVersionDismissed] = useState(false); + const [versionDismissed] = useState(false); useEffect(() => { if (isElectron()) { @@ -47,10 +47,6 @@ export function VersionCheckModal({ } }; - const handleVersionDismiss = () => { - setVersionDismissed(true); - }; - const handleDownloadUpdate = () => { if (versionInfo?.latest_release?.html_url) { window.open(versionInfo.latest_release.html_url, "_blank"); diff --git a/src/lib/frontend-logger.ts b/src/lib/frontend-logger.ts index b0558de7..367c4060 100644 --- a/src/lib/frontend-logger.ts +++ b/src/lib/frontend-logger.ts @@ -17,7 +17,7 @@ export interface LogContext { errorCode?: string; errorMessage?: string; - [key: string]: any; + [key: string]: unknown; } class FrontendLogger { @@ -218,7 +218,6 @@ class FrontendLogger { context?: LogContext, ): void { const cleanUrl = this.sanitizeUrl(url); - const shortUrl = this.getShortUrl(cleanUrl); const statusIcon = this.getStatusIcon(status); const performanceIcon = this.getPerformanceIcon(responseTime); @@ -244,7 +243,6 @@ class FrontendLogger { context?: LogContext, ): void { const cleanUrl = this.sanitizeUrl(url); - const shortUrl = this.getShortUrl(cleanUrl); const statusIcon = this.getStatusIcon(status); this.error(`← ${statusIcon} ${status} ${errorMessage}`, undefined, { @@ -265,7 +263,6 @@ class FrontendLogger { context?: LogContext, ): void { const cleanUrl = this.sanitizeUrl(url); - const shortUrl = this.getShortUrl(cleanUrl); this.error(`🌐 Network Error: ${errorMessage}`, undefined, { ...context, @@ -279,7 +276,6 @@ class FrontendLogger { authError(method: string, url: string, context?: LogContext): void { const cleanUrl = this.sanitizeUrl(url); - const shortUrl = this.getShortUrl(cleanUrl); this.security(`🔐 Authentication Required`, { ...context, @@ -298,7 +294,6 @@ class FrontendLogger { context?: LogContext, ): void { const cleanUrl = this.sanitizeUrl(url); - const shortUrl = this.getShortUrl(cleanUrl); this.retry(`🔄 Retry ${attempt}/${maxAttempts}`, { ...context, @@ -384,5 +379,6 @@ export const tunnelLogger = new FrontendLogger("TUNNEL", "📡", "#1e3a8a"); export const fileLogger = new FrontendLogger("FILE", "📁", "#1e3a8a"); export const statsLogger = new FrontendLogger("STATS", "📊", "#22c55e"); export const systemLogger = new FrontendLogger("SYSTEM", "🚀", "#1e3a8a"); +export const homepageLogger = new FrontendLogger("HOMEPAGE", "🏠", "#ec4899"); export const logger = systemLogger; diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index e24e7baa..62abc045 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -191,6 +191,40 @@ "enableRightClickCopyPaste": "Enable right‑click copy/paste", "shareIdeas": "Have ideas for what should come next for ssh tools? Share them on" }, + "snippets": { + "title": "Snippets", + "new": "New Snippet", + "create": "Create Snippet", + "edit": "Edit Snippet", + "run": "Run", + "empty": "No snippets yet", + "emptyHint": "Create a snippet to save commonly used commands", + "name": "Name", + "description": "Description", + "content": "Command", + "namePlaceholder": "e.g., Restart Nginx", + "descriptionPlaceholder": "Optional description", + "contentPlaceholder": "e.g., sudo systemctl restart nginx", + "nameRequired": "Name is required", + "contentRequired": "Command is required", + "createDescription": "Create a new command snippet for quick execution", + "editDescription": "Edit this command snippet", + "deleteConfirmTitle": "Delete Snippet", + "deleteConfirmDescription": "Are you sure you want to delete \"{{name}}\"?", + "createSuccess": "Snippet created successfully", + "updateSuccess": "Snippet updated successfully", + "deleteSuccess": "Snippet deleted successfully", + "createFailed": "Failed to create snippet", + "updateFailed": "Failed to update snippet", + "deleteFailed": "Failed to delete snippet", + "failedToFetch": "Failed to fetch snippets", + "executeSuccess": "Executing: {{name}}", + "copySuccess": "Copied \"{{name}}\" to clipboard", + "runTooltip": "Execute this snippet in the terminal", + "copyTooltip": "Copy snippet to clipboard", + "editTooltip": "Edit this snippet", + "deleteTooltip": "Delete this snippet" + }, "homepage": { "loggedInTitle": "Logged in!", "loggedInMessage": "You are logged in! Use the sidebar to access all available tools. To get started, create an SSH Host in the SSH Manager tab. Once created, you can connect to that host using the other apps in the sidebar.", @@ -357,6 +391,7 @@ "admin": "Admin", "userProfile": "User Profile", "tools": "Tools", + "snippets": "Snippets", "newTab": "New Tab", "splitScreen": "Split Screen", "closeTab": "Close Tab", @@ -410,10 +445,12 @@ "general": "General", "userRegistration": "User Registration", "allowNewAccountRegistration": "Allow new account registration", + "allowPasswordLogin": "Allow username/password login", "missingRequiredFields": "Missing required fields: {{fields}}", "oidcConfigurationUpdated": "OIDC configuration updated successfully!", "failedToFetchOidcConfig": "Failed to fetch OIDC configuration", "failedToFetchRegistrationStatus": "Failed to fetch registration status", + "failedToFetchPasswordLoginStatus": "Failed to fetch password login status", "failedToFetchUsers": "Failed to fetch users", "oidcConfigurationDisabled": "OIDC configuration disabled successfully!", "failedToUpdateOidcConfig": "Failed to update OIDC configuration", @@ -669,14 +706,34 @@ "terminal": "Terminal", "tunnel": "Tunnel", "fileManager": "File Manager", + "serverStats": "Server Stats", "hostViewer": "Host Viewer", + "enableServerStats": "Enable Server Stats", + "enableServerStatsDesc": "Enable/disable server statistics collection for this host", + "displayItems": "Display Items", + "displayItemsDesc": "Choose which metrics to display on the server stats page", + "enableCpu": "CPU Usage", + "enableMemory": "Memory Usage", + "enableDisk": "Disk Usage", + "enableNetwork": "Network Statistics (Coming Soon)", + "enableProcesses": "Process Count (Coming Soon)", + "enableUptime": "Uptime (Coming Soon)", + "enableHostname": "Hostname (Coming Soon)", + "enableOs": "Operating System (Coming Soon)", + "customCommands": "Custom Commands (Coming Soon)", + "customCommandsDesc": "Define custom shutdown and reboot commands for this server", + "shutdownCommand": "Shutdown Command", + "rebootCommand": "Reboot Command", "confirmRemoveFromFolder": "Are you sure you want to remove \"{{name}}\" from folder \"{{folder}}\"? The host will be moved to \"No Folder\".", "removedFromFolder": "Host \"{{name}}\" removed from folder successfully", "failedToRemoveFromFolder": "Failed to remove host from folder", "folderRenamed": "Folder \"{{oldName}}\" renamed to \"{{newName}}\" successfully", "failedToRenameFolder": "Failed to rename folder", "movedToFolder": "Host \"{{name}}\" moved to \"{{folder}}\" successfully", - "failedToMoveToFolder": "Failed to move host to folder" + "failedToMoveToFolder": "Failed to move host to folder", + "statistics": "Statistics", + "enabledWidgets": "Enabled Widgets", + "enabledWidgetsDesc": "Select which statistics widgets to display for this host" }, "terminal": { "title": "Terminal", @@ -710,7 +767,11 @@ "connectionTimeout": "Connection timeout", "terminalTitle": "Terminal - {{host}}", "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Running {{command}} - {{host}}" + "runTitle": "Running {{command}} - {{host}}", + "totpRequired": "Two-Factor Authentication Required", + "totpCodeLabel": "Verification Code", + "totpPlaceholder": "000000", + "totpVerify": "Verify" }, "fileManager": { "title": "File Manager", @@ -994,7 +1055,9 @@ "fileComparison": "File Comparison: {{file1}} vs {{file2}}", "fileTooLarge": "File too large: {{error}}", "sshConnectionFailed": "SSH connection failed. Please check your connection to {{name}} ({{ip}}:{{port}})", - "loadFileFailed": "Failed to load file: {{error}}" + "loadFileFailed": "Failed to load file: {{error}}", + "connectedSuccessfully": "Connected successfully", + "totpVerificationFailed": "TOTP verification failed" }, "tunnels": { "title": "SSH Tunnels", @@ -1083,6 +1146,7 @@ "loadAverageNA": "Avg: N/A", "cpuUsage": "CPU Usage", "memoryUsage": "Memory Usage", + "diskUsage": "Disk Usage", "rootStorageSpace": "Root Storage Space", "of": "of", "feedbackMessage": "Have ideas for what should come next for server management? Share them on", @@ -1094,9 +1158,29 @@ "refreshing": "Refreshing...", "serverOffline": "Server Offline", "cannotFetchMetrics": "Cannot fetch metrics from offline server", + "totpRequired": "TOTP Authentication Required", + "totpUnavailable": "Server Stats unavailable for TOTP-enabled servers", "load": "Load", "free": "Free", - "available": "Available" + "available": "Available", + "editLayout": "Edit Layout", + "cancelEdit": "Cancel", + "addWidget": "Add Widget", + "saveLayout": "Save Layout", + "unsavedChanges": "Unsaved changes", + "layoutSaved": "Layout saved successfully", + "failedToSaveLayout": "Failed to save layout", + "systemInfo": "System Information", + "hostname": "Hostname", + "operatingSystem": "Operating System", + "kernel": "Kernel", + "totalUptime": "Total Uptime", + "seconds": "seconds", + "networkInterfaces": "Network Interfaces", + "noInterfacesFound": "No network interfaces found", + "totalProcesses": "Total Processes", + "running": "Running", + "noProcessesFound": "No processes found" }, "auth": { "loginTitle": "Login to Termix", diff --git a/src/locales/zh/translation.json b/src/locales/zh/translation.json index cd1c0ef0..606d2728 100644 --- a/src/locales/zh/translation.json +++ b/src/locales/zh/translation.json @@ -189,6 +189,40 @@ "enableRightClickCopyPaste": "启用右键复制/粘贴", "shareIdeas": "对 SSH 工具有什么想法?在此分享" }, + "snippets": { + "title": "代码片段", + "new": "新建片段", + "create": "创建代码片段", + "edit": "编辑代码片段", + "run": "运行", + "empty": "暂无代码片段", + "emptyHint": "创建代码片段以保存常用命令", + "name": "名称", + "description": "描述", + "content": "命令", + "namePlaceholder": "例如: 重启 Nginx", + "descriptionPlaceholder": "可选描述", + "contentPlaceholder": "例如: sudo systemctl restart nginx", + "nameRequired": "名称不能为空", + "contentRequired": "命令不能为空", + "createDescription": "创建新的命令片段以便快速执行", + "editDescription": "编辑此命令片段", + "deleteConfirmTitle": "删除代码片段", + "deleteConfirmDescription": "确定要删除 \"{{name}}\" 吗?", + "createSuccess": "代码片段创建成功", + "updateSuccess": "代码片段更新成功", + "deleteSuccess": "代码片段删除成功", + "createFailed": "创建代码片段失败", + "updateFailed": "更新代码片段失败", + "deleteFailed": "删除代码片段失败", + "failedToFetch": "获取代码片段失败", + "executeSuccess": "正在执行: {{name}}", + "copySuccess": "已复制 \"{{name}}\" 到剪贴板", + "runTooltip": "在终端中执行此片段", + "copyTooltip": "复制片段到剪贴板", + "editTooltip": "编辑此片段", + "deleteTooltip": "删除此片段" + }, "homepage": { "loggedInTitle": "登录成功!", "loggedInMessage": "您已登录!使用侧边栏访问所有可用工具。要开始使用,请在 SSH 管理器选项卡中创建 SSH 主机。创建后,您可以使用侧边栏中的其他应用程序连接到该主机。", @@ -343,6 +377,7 @@ "admin": "管理员", "userProfile": "用户资料", "tools": "工具", + "snippets": "代码片段", "newTab": "新标签页", "splitScreen": "分屏", "closeTab": "关闭标签页", @@ -396,10 +431,12 @@ "general": "常规", "userRegistration": "用户注册", "allowNewAccountRegistration": "允许新账户注册", + "allowPasswordLogin": "允许用户名/密码登录", "missingRequiredFields": "缺少必填字段:{{fields}}", "oidcConfigurationUpdated": "OIDC 配置更新成功!", "failedToFetchOidcConfig": "获取 OIDC 配置失败", "failedToFetchRegistrationStatus": "获取注册状态失败", + "failedToFetchPasswordLoginStatus": "获取密码登录状态失败", "failedToFetchUsers": "获取用户列表失败", "oidcConfigurationDisabled": "OIDC 配置禁用成功!", "failedToUpdateOidcConfig": "更新 OIDC 配置失败", @@ -691,19 +728,44 @@ "terminal": "终端", "tunnel": "隧道", "fileManager": "文件管理器", + "serverStats": "服务器统计", + "hostViewer": "主机查看器", + "enableServerStats": "启用服务器统计", + "enableServerStatsDesc": "启用/禁用此主机的服务器统计信息收集", + "displayItems": "显示项目", + "displayItemsDesc": "选择在服务器统计页面上显示哪些指标", + "enableCpu": "CPU使用率", + "enableMemory": "内存使用率", + "enableDisk": "磁盘使用率", + "enableNetwork": "网络统计(即将推出)", + "enableProcesses": "进程数(即将推出)", + "enableUptime": "运行时间(即将推出)", + "enableHostname": "主机名(即将推出)", + "enableOs": "操作系统(即将推出)", + "customCommands": "自定义命令(即将推出)", + "customCommandsDesc": "为此服务器定义自定义关机和重启命令", + "shutdownCommand": "关机命令", + "rebootCommand": "重启命令", "confirmRemoveFromFolder": "确定要将\"{{name}}\"从文件夹\"{{folder}}\"中移除吗?主机将被移动到\"无文件夹\"。", "removedFromFolder": "主机\"{{name}}\"已成功从文件夹中移除", "failedToRemoveFromFolder": "从文件夹中移除主机失败", "folderRenamed": "文件夹\"{{oldName}}\"已成功重命名为\"{{newName}}\"", "failedToRenameFolder": "重命名文件夹失败", "movedToFolder": "主机\"{{name}}\"已成功移动到\"{{folder}}\"", - "failedToMoveToFolder": "移动主机到文件夹失败" + "failedToMoveToFolder": "移动主机到文件夹失败", + "statistics": "统计", + "enabledWidgets": "已启用组件", + "enabledWidgetsDesc": "选择要为此主机显示的统计组件" }, "terminal": { "title": "终端", "terminalTitle": "终端 - {{host}}", "terminalWithPath": "终端 - {{host}}:{{path}}", "runTitle": "运行 {{command}} - {{host}}", + "totpRequired": "需要双因素认证", + "totpCodeLabel": "验证码", + "totpPlaceholder": "000000", + "totpVerify": "验证", "connect": "连接主机", "disconnect": "断开连接", "clear": "清屏", @@ -985,7 +1047,9 @@ "fileComparison": "文件对比:{{file1}} 与 {{file2}}", "fileTooLarge": "文件过大:{{error}}", "sshConnectionFailed": "SSH 连接失败。请检查与 {{name}} ({{ip}}:{{port}}) 的连接", - "loadFileFailed": "加载文件失败:{{error}}" + "loadFileFailed": "加载文件失败:{{error}}", + "connectedSuccessfully": "连接成功", + "totpVerificationFailed": "TOTP 验证失败" }, "tunnels": { "title": "SSH 隧道", @@ -1063,6 +1127,7 @@ "loadAverageNA": "平均: N/A", "cpuUsage": "CPU 使用率", "memoryUsage": "内存使用率", + "diskUsage": "磁盘使用率", "rootStorageSpace": "根目录存储空间", "of": "的", "feedbackMessage": "对服务器管理的下一步功能有想法?在这里分享吧", @@ -1073,7 +1138,29 @@ "refreshing": "正在刷新...", "serverOffline": "服务器离线", "cannotFetchMetrics": "无法从离线服务器获取指标", - "load": "负载" + "totpRequired": "需要 TOTP 认证", + "totpUnavailable": "启用了 TOTP 的服务器无法使用服务器统计功能", + "load": "负载", + "free": "空闲", + "available": "可用", + "editLayout": "编辑布局", + "cancelEdit": "取消", + "addWidget": "添加小组件", + "saveLayout": "保存布局", + "unsavedChanges": "有未保存的更改", + "layoutSaved": "布局保存成功", + "failedToSaveLayout": "保存布局失败", + "systemInfo": "系统信息", + "hostname": "主机名", + "operatingSystem": "操作系统", + "kernel": "内核", + "totalUptime": "总运行时间", + "seconds": "秒", + "networkInterfaces": "网络接口", + "noInterfacesFound": "未找到网络接口", + "totalProcesses": "总进程数", + "running": "运行中", + "noProcessesFound": "未找到进程" }, "auth": { "loginTitle": "登录 Termix", diff --git a/src/main.tsx b/src/main.tsx index 55a6815f..230db6da 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import { StrictMode, useEffect, useState, useRef } from "react"; import { createRoot } from "react-dom/client"; import "./index.css"; @@ -9,7 +10,6 @@ import { isElectron } from "./ui/main-axios.ts"; function useWindowWidth() { const [width, setWidth] = useState(window.innerWidth); - const [isMobile, setIsMobile] = useState(window.innerWidth < 768); const lastSwitchTime = useRef(0); const isCurrentlyMobile = useRef(window.innerWidth < 768); const hasSwitchedOnce = useRef(false); @@ -36,7 +36,6 @@ function useWindowWidth() { isCurrentlyMobile.current = newIsMobile; hasSwitchedOnce.current = true; setWidth(newWidth); - setIsMobile(newIsMobile); } else { setWidth(newWidth); } diff --git a/src/types/electron.d.ts b/src/types/electron.d.ts index 6a544f20..ec3321e4 100644 --- a/src/types/electron.d.ts +++ b/src/types/electron.d.ts @@ -1,22 +1,49 @@ +interface ServerConfig { + serverUrl?: string; + [key: string]: unknown; +} + +interface ConnectionTestResult { + success: boolean; + error?: string; + [key: string]: unknown; +} + +interface DialogOptions { + title?: string; + defaultPath?: string; + buttonLabel?: string; + filters?: Array<{ name: string; extensions: string[] }>; + properties?: string[]; + [key: string]: unknown; +} + +interface DialogResult { + canceled: boolean; + filePath?: string; + filePaths?: string[]; + [key: string]: unknown; +} + export interface ElectronAPI { getAppVersion: () => Promise; getPlatform: () => Promise; - getServerConfig: () => Promise; - saveServerConfig: (config: any) => Promise; - testServerConnection: (serverUrl: string) => Promise; + getServerConfig: () => Promise; + saveServerConfig: (config: ServerConfig) => Promise<{ success: boolean }>; + testServerConnection: (serverUrl: string) => Promise; - showSaveDialog: (options: any) => Promise; - showOpenDialog: (options: any) => Promise; + showSaveDialog: (options: DialogOptions) => Promise; + showOpenDialog: (options: DialogOptions) => Promise; - onUpdateAvailable: (callback: Function) => void; - onUpdateDownloaded: (callback: Function) => void; + onUpdateAvailable: (callback: () => void) => void; + onUpdateDownloaded: (callback: () => void) => void; removeAllListeners: (channel: string) => void; isElectron: boolean; isDev: boolean; - invoke: (channel: string, ...args: any[]) => Promise; + invoke: (channel: string, ...args: unknown[]) => Promise; createTempFile: (fileData: { fileName: string; diff --git a/src/types/index.ts b/src/types/index.ts index ee7cedb2..f4748628 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,9 +1,9 @@ // ============================================================================ // CENTRAL TYPE DEFINITIONS // ============================================================================ -// This file contains all shared interfaces and types used across the application import type { Client } from "ssh2"; +import type { Request } from "express"; // ============================================================================ // SSH HOST TYPES @@ -35,6 +35,7 @@ export interface SSHHost { enableFileManager: boolean; defaultPath: string; tunnelConnections: TunnelConnection[]; + statsConfig?: string; createdAt: string; updatedAt: string; } @@ -57,7 +58,8 @@ export interface SSHHostData { enableTunnel?: boolean; enableFileManager?: boolean; defaultPath?: string; - tunnelConnections?: any[]; + tunnelConnections?: TunnelConnection[]; + statsConfig?: string; } // ============================================================================ @@ -261,8 +263,9 @@ export interface TabContextTab { | "file_manager" | "user_profile"; title: string; - hostConfig?: any; - terminalRef?: React.RefObject; + hostConfig?: SSHHost; + terminalRef?: any; + initialTab?: string; // For ssh_manager: "host_viewer" | "add_host" | "credentials" | "add_credential" } // ============================================================================ @@ -303,7 +306,7 @@ export type KeyType = "rsa" | "ecdsa" | "ed25519"; // API RESPONSE TYPES // ============================================================================ -export interface ApiResponse { +export interface ApiResponse { data?: T; error?: string; message?: string; @@ -337,6 +340,7 @@ export interface CredentialSelectorProps { export interface HostManagerProps { onSelectView?: (view: string) => void; isTopbarOpen?: boolean; + initialTab?: string; } export interface SSHManagerHostEditorProps { @@ -366,13 +370,13 @@ export interface SSHTunnelViewerProps { action: "connect" | "disconnect" | "cancel", host: SSHHost, tunnelIndex: number, - ) => Promise + ) => Promise >; onTunnelAction?: ( action: "connect" | "disconnect" | "cancel", host: SSHHost, tunnelIndex: number, - ) => Promise; + ) => Promise; } export interface FileManagerProps { @@ -400,7 +404,7 @@ export interface SSHTunnelObjectProps { action: "connect" | "disconnect" | "cancel", host: SSHHost, tunnelIndex: number, - ) => Promise; + ) => Promise; compact?: boolean; bare?: boolean; } @@ -413,6 +417,26 @@ export interface FolderStats { }>; } +// ============================================================================ +// SNIPPETS TYPES +// ============================================================================ + +export interface Snippet { + id: number; + userId: string; + name: string; + content: string; + description?: string; + createdAt: string; + updatedAt: string; +} + +export interface SnippetData { + name: string; + content: string; + description?: string; +} + // ============================================================================ // BACKEND TYPES // ============================================================================ @@ -439,3 +463,95 @@ export type Optional = Omit & Partial>; export type RequiredFields = T & Required>; export type PartialExcept = Partial & Pick; + +// ============================================================================ +// EXPRESS REQUEST TYPES +// ============================================================================ + +export interface AuthenticatedRequest extends Request { + userId: string; + user?: { + id: string; + username: string; + isAdmin: boolean; + }; +} + +// ============================================================================ +// GITHUB API TYPES +// ============================================================================ + +export interface GitHubAsset { + id: number; + name: string; + size: number; + download_count: number; + browser_download_url: string; +} + +export interface GitHubRelease { + id: number; + tag_name: string; + name: string; + body: string; + published_at: string; + html_url: string; + assets: GitHubAsset[]; + prerelease: boolean; + draft: boolean; +} + +export interface GitHubAPIResponse { + data: T; + cached: boolean; + cache_age?: number; + timestamp?: number; +} + +// ============================================================================ +// CACHE TYPES +// ============================================================================ + +export interface CacheEntry { + data: T; + timestamp: number; + expiresAt: number; +} + +// ============================================================================ +// DATABASE EXPORT/IMPORT TYPES +// ============================================================================ + +export interface ExportSummary { + sshHostsImported: number; + sshCredentialsImported: number; + fileManagerItemsImported: number; + dismissedAlertsImported: number; + credentialUsageImported: number; + settingsImported: number; + skippedItems: number; + errors: string[]; +} + +export interface ImportResult { + success: boolean; + summary: ExportSummary; +} + +export interface ExportRequestBody { + password: string; +} + +export interface ImportRequestBody { + password: string; +} + +export interface ExportPreviewBody { + scope?: string; + includeCredentials?: boolean; +} + +export interface RestoreRequestBody { + backupPath: string; + targetPath?: string; +} diff --git a/src/types/stats-widgets.ts b/src/types/stats-widgets.ts new file mode 100644 index 00000000..3f083f17 --- /dev/null +++ b/src/types/stats-widgets.ts @@ -0,0 +1,16 @@ +export type WidgetType = + | "cpu" + | "memory" + | "disk" + | "network" + | "uptime" + | "processes" + | "system"; + +export interface StatsConfig { + enabledWidgets: WidgetType[]; +} + +export const DEFAULT_STATS_CONFIG: StatsConfig = { + enabledWidgets: ["cpu", "memory", "disk", "network", "uptime", "system"], +}; diff --git a/src/ui/Desktop/Admin/AdminSettings.tsx b/src/ui/Desktop/Admin/AdminSettings.tsx index b04a0c20..6d0ff0f8 100644 --- a/src/ui/Desktop/Admin/AdminSettings.tsx +++ b/src/ui/Desktop/Admin/AdminSettings.tsx @@ -26,7 +26,6 @@ import { Trash2, Users, Database, - Key, Lock, Download, Upload, @@ -37,8 +36,10 @@ import { useConfirmation } from "@/hooks/use-confirmation.ts"; import { getOIDCConfig, getRegistrationAllowed, + getPasswordLoginAllowed, getUserList, updateRegistrationAllowed, + updatePasswordLoginAllowed, updateOIDCConfig, disableOIDCConfig, makeUserAdmin, @@ -63,6 +64,9 @@ export function AdminSettings({ const [allowRegistration, setAllowRegistration] = React.useState(true); const [regLoading, setRegLoading] = React.useState(false); + const [allowPasswordLogin, setAllowPasswordLogin] = React.useState(true); + const [passwordLoginLoading, setPasswordLoginLoading] = React.useState(false); + const [oidcConfig, setOidcConfig] = React.useState({ client_id: "", client_secret: "", @@ -107,7 +111,6 @@ export function AdminSettings({ const [showPasswordInput, setShowPasswordInput] = React.useState(false); const [importPassword, setImportPassword] = React.useState(""); - // Only local accounts need to confirm their password before we post the import request. const requiresImportPassword = React.useMemo( () => !currentUser?.is_oidc, [currentUser?.is_oidc], @@ -115,7 +118,8 @@ export function AdminSettings({ React.useEffect(() => { if (isElectron()) { - const serverUrl = (window as any).configuredServerUrl; + const serverUrl = (window as { configuredServerUrl?: string }) + .configuredServerUrl; if (!serverUrl) { return; } @@ -152,7 +156,8 @@ export function AdminSettings({ React.useEffect(() => { if (isElectron()) { - const serverUrl = (window as any).configuredServerUrl; + const serverUrl = (window as { configuredServerUrl?: string }) + .configuredServerUrl; if (!serverUrl) { return; } @@ -171,9 +176,32 @@ export function AdminSettings({ }); }, []); + React.useEffect(() => { + if (isElectron()) { + const serverUrl = (window as { configuredServerUrl?: string }) + .configuredServerUrl; + if (!serverUrl) { + return; + } + } + + getPasswordLoginAllowed() + .then((res) => { + if (typeof res?.allowed === "boolean") { + setAllowPasswordLogin(res.allowed); + } + }) + .catch((err) => { + if (err.code !== "NO_SERVER_CONFIGURED") { + toast.error(t("admin.failedToFetchPasswordLoginStatus")); + } + }); + }, []); + const fetchUsers = async () => { if (isElectron()) { - const serverUrl = (window as any).configuredServerUrl; + const serverUrl = (window as { configuredServerUrl?: string }) + .configuredServerUrl; if (!serverUrl) { return; } @@ -202,6 +230,16 @@ export function AdminSettings({ } }; + const handleTogglePasswordLogin = async (checked: boolean) => { + setPasswordLoginLoading(true); + try { + await updatePasswordLoginAllowed(checked); + setAllowPasswordLogin(checked); + } finally { + setPasswordLoginLoading(false); + } + }; + const handleOIDCConfigSubmit = async (e: React.FormEvent) => { e.preventDefault(); setOidcLoading(true); @@ -228,9 +266,10 @@ export function AdminSettings({ try { await updateOIDCConfig(oidcConfig); toast.success(t("admin.oidcConfigurationUpdated")); - } catch (err: any) { + } catch (err: unknown) { setOidcError( - err?.response?.data?.error || t("admin.failedToUpdateOidcConfig"), + (err as { response?: { data?: { error?: string } } })?.response?.data + ?.error || t("admin.failedToUpdateOidcConfig"), ); } finally { setOidcLoading(false); @@ -251,9 +290,10 @@ export function AdminSettings({ toast.success(t("admin.userIsNowAdmin", { username: newAdminUsername })); setNewAdminUsername(""); fetchUsers(); - } catch (err: any) { + } catch (err: unknown) { setMakeAdminError( - err?.response?.data?.error || t("admin.failedToMakeUserAdmin"), + (err as { response?: { data?: { error?: string } } })?.response?.data + ?.error || t("admin.failedToMakeUserAdmin"), ); } finally { setMakeAdminLoading(false); @@ -266,7 +306,7 @@ export function AdminSettings({ await removeAdminStatus(username); toast.success(t("admin.adminStatusRemoved", { username })); fetchUsers(); - } catch (err: any) { + } catch { toast.error(t("admin.failedToRemoveAdminStatus")); } }); @@ -280,7 +320,7 @@ export function AdminSettings({ await deleteUser(username); toast.success(t("admin.userDeletedSuccessfully", { username })); fetchUsers(); - } catch (err: any) { + } catch { toast.error(t("admin.failedToDeleteUser")); } }, @@ -310,7 +350,7 @@ export function AdminSettings({ window.location.hostname === "127.0.0.1"); const apiUrl = isElectron() - ? `${(window as any).configuredServerUrl}/database/export` + ? `${(window as { configuredServerUrl?: string }).configuredServerUrl}/database/export` : isDev ? `http://localhost:30001/database/export` : `${window.location.protocol}//${window.location.host}/database/export`; @@ -351,7 +391,7 @@ export function AdminSettings({ toast.error(error.error || t("admin.databaseExportFailed")); } } - } catch (err) { + } catch { toast.error(t("admin.databaseExportFailed")); } finally { setExportLoading(false); @@ -380,7 +420,7 @@ export function AdminSettings({ window.location.hostname === "127.0.0.1"); const apiUrl = isElectron() - ? `${(window as any).configuredServerUrl}/database/import` + ? `${(window as { configuredServerUrl?: string }).configuredServerUrl}/database/import` : isDev ? `http://localhost:30001/database/import` : `${window.location.protocol}//${window.location.host}/database/import`; @@ -446,7 +486,7 @@ export function AdminSettings({ toast.error(error.error || t("admin.databaseImportFailed")); } } - } catch (err) { + } catch { toast.error(t("admin.databaseImportFailed")); } finally { setImportLoading(false); @@ -516,6 +556,14 @@ export function AdminSettings({ /> {t("admin.allowNewAccountRegistration")} +
@@ -702,9 +750,13 @@ export function AdminSettings({ try { await disableOIDCConfig(); toast.success(t("admin.oidcConfigurationDisabled")); - } catch (err: any) { + } catch (err: unknown) { setOidcError( - err?.response?.data?.error || + ( + err as { + response?: { data?: { error?: string } }; + } + )?.response?.data?.error || t("admin.failedToDisableOidcConfig"), ); } finally { diff --git a/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx b/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx index 9303c0b8..d4e0d7d3 100644 --- a/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx +++ b/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx @@ -42,9 +42,9 @@ export function CredentialEditor({ onFormSubmit, }: CredentialEditorProps) { const { t } = useTranslation(); - const [credentials, setCredentials] = useState([]); + const [, setCredentials] = useState([]); const [folders, setFolders] = useState([]); - const [loading, setLoading] = useState(true); + const [, setLoading] = useState(true); const [fullCredentialDetails, setFullCredentialDetails] = useState(null); @@ -79,7 +79,8 @@ export function CredentialEditor({ ].sort() as string[]; setFolders(uniqueFolders); - } catch (error) { + } catch { + // Failed to load credentials } finally { setLoading(false); } @@ -94,7 +95,7 @@ export function CredentialEditor({ try { const fullDetails = await getCredentialDetails(editingCredential.id); setFullCredentialDetails(fullDetails); - } catch (error) { + } catch { toast.error(t("credentials.failedToFetchCredentialDetails")); } } else { @@ -154,7 +155,9 @@ export function CredentialEditor({ type FormData = z.infer; const form = useForm({ - resolver: zodResolver(formSchema) as any, + resolver: zodResolver(formSchema) as unknown as Parameters< + typeof useForm + >[0]["resolver"], defaultValues: { name: "", description: "", @@ -197,7 +200,7 @@ export function CredentialEditor({ formData.publicKey = fullCredentialDetails.publicKey || ""; formData.keyPassword = fullCredentialDetails.keyPassword || ""; formData.keyType = - (fullCredentialDetails.keyType as any) || ("auto" as const); + (fullCredentialDetails.keyType as string) || ("auto" as const); } form.reset(formData); @@ -636,10 +639,6 @@ export function CredentialEditor({ form.setValue("key", null); form.setValue("keyPassword", ""); form.setValue("keyType", "auto"); - - if (newAuthType === "password") { - } else if (newAuthType === "key") { - } }} className="flex-1 flex flex-col h-full min-h-0" > diff --git a/src/ui/Desktop/Apps/Credentials/CredentialSelector.tsx b/src/ui/Desktop/Apps/Credentials/CredentialSelector.tsx index 4e9b6843..91fefd8e 100644 --- a/src/ui/Desktop/Apps/Credentials/CredentialSelector.tsx +++ b/src/ui/Desktop/Apps/Credentials/CredentialSelector.tsx @@ -35,7 +35,7 @@ export function CredentialSelector({ ? data : data.credentials || data.data || []; setCredentials(credentialsArray); - } catch (error) { + } catch { const { toast } = await import("sonner"); toast.error(t("credentials.failedToFetchCredentials")); setCredentials([]); diff --git a/src/ui/Desktop/Apps/Credentials/CredentialViewer.tsx b/src/ui/Desktop/Apps/Credentials/CredentialViewer.tsx index 8edf5279..65be063c 100644 --- a/src/ui/Desktop/Apps/Credentials/CredentialViewer.tsx +++ b/src/ui/Desktop/Apps/Credentials/CredentialViewer.tsx @@ -70,7 +70,7 @@ const CredentialViewer: React.FC = ({ try { const response = await getCredentialDetails(credential.id); setCredentialDetails(response); - } catch (error) { + } catch { toast.error(t("credentials.failedToFetchCredentialDetails")); } }; @@ -79,7 +79,7 @@ const CredentialViewer: React.FC = ({ try { const response = await getCredentialHosts(credential.id); setHostsUsing(response); - } catch (error) { + } catch { toast.error(t("credentials.failedToFetchHostsUsing")); } finally { setLoading(false); @@ -97,7 +97,7 @@ const CredentialViewer: React.FC = ({ try { await navigator.clipboard.writeText(text); toast.success(t("copiedToClipboard", { field: fieldName })); - } catch (error) { + } catch { toast.error(t("credentials.failedToCopy")); } }; diff --git a/src/ui/Desktop/Apps/Credentials/CredentialsManager.tsx b/src/ui/Desktop/Apps/Credentials/CredentialsManager.tsx index 553f228b..aedae3d5 100644 --- a/src/ui/Desktop/Apps/Credentials/CredentialsManager.tsx +++ b/src/ui/Desktop/Apps/Credentials/CredentialsManager.tsx @@ -9,21 +9,7 @@ import { AccordionItem, AccordionTrigger, } from "@/components/ui/accordion"; -import { - Sheet, - SheetContent, - SheetDescription, - SheetFooter, - SheetHeader, - SheetTitle, -} from "@/components/ui/sheet"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; +import { Sheet, SheetContent } from "@/components/ui/sheet"; import { Tooltip, TooltipContent, @@ -37,7 +23,6 @@ import { Edit, Trash2, Shield, - Pin, Tag, Info, FolderMinus, @@ -75,9 +60,7 @@ export function CredentialsManager({ const [error, setError] = useState(null); const [searchQuery, setSearchQuery] = useState(""); const [showViewer, setShowViewer] = useState(false); - const [viewingCredential, setViewingCredential] = useState( - null, - ); + const [viewingCredential] = useState(null); const [draggedCredential, setDraggedCredential] = useState( null, ); @@ -88,7 +71,15 @@ export function CredentialsManager({ const [showDeployDialog, setShowDeployDialog] = useState(false); const [deployingCredential, setDeployingCredential] = useState(null); - const [availableHosts, setAvailableHosts] = useState([]); + const [availableHosts, setAvailableHosts] = useState< + Array<{ + id: number; + name: string; + ip: string; + port: number; + username: string; + }> + >([]); const [selectedHostId, setSelectedHostId] = useState(""); const [deployLoading, setDeployLoading] = useState(false); const [hostSearchQuery, setHostSearchQuery] = useState(""); @@ -153,7 +144,7 @@ export function CredentialsManager({ const data = await getCredentials(); setCredentials(data); setError(null); - } catch (err) { + } catch { setError(t("credentials.failedToFetchCredentials")); } finally { setLoading(false); @@ -224,10 +215,13 @@ export function CredentialsManager({ ); await fetchCredentials(); window.dispatchEvent(new CustomEvent("credentials:changed")); - } catch (err: any) { - if (err.response?.data?.details) { + } catch (err: unknown) { + const error = err as { + response?: { data?: { error?: string; details?: string } }; + }; + if (error.response?.data?.details) { toast.error( - `${err.response.data.error}\n${err.response.data.details}`, + `${error.response.data.error}\n${error.response.data.details}`, ); } else { toast.error(t("credentials.failedToDeleteCredential")); @@ -256,7 +250,7 @@ export function CredentialsManager({ ); await fetchCredentials(); window.dispatchEvent(new CustomEvent("credentials:changed")); - } catch (err) { + } catch { toast.error(t("credentials.failedToRemoveFromFolder")); } finally { setOperationLoading(false); @@ -285,7 +279,7 @@ export function CredentialsManager({ window.dispatchEvent(new CustomEvent("credentials:changed")); setEditingFolder(null); setEditingFolderName(""); - } catch (err) { + } catch { toast.error(t("credentials.failedToRenameFolder")); } finally { setOperationLoading(false); @@ -325,7 +319,7 @@ export function CredentialsManager({ setDragOverFolder(folderName); }; - const handleDragLeave = (e: React.DragEvent) => { + const handleDragLeave = () => { dragCounter.current--; if (dragCounter.current === 0) { setDragOverFolder(null); @@ -359,7 +353,7 @@ export function CredentialsManager({ ); await fetchCredentials(); window.dispatchEvent(new CustomEvent("credentials:changed")); - } catch (err) { + } catch { toast.error(t("credentials.failedToMoveToFolder")); } finally { setOperationLoading(false); diff --git a/src/ui/Desktop/Homepage/HomepageAlertCard.tsx b/src/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertCard.tsx similarity index 97% rename from src/ui/Desktop/Homepage/HomepageAlertCard.tsx rename to src/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertCard.tsx index 96637d6a..c3883f49 100644 --- a/src/ui/Desktop/Homepage/HomepageAlertCard.tsx +++ b/src/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertCard.tsx @@ -17,7 +17,7 @@ import { AlertCircle, } from "lucide-react"; import { useTranslation } from "react-i18next"; -import type { TermixAlert } from "../../../types/index.js"; +import type { TermixAlert } from "../../../../../../types"; interface AlertCardProps { alert: TermixAlert; @@ -67,7 +67,7 @@ const getTypeBadgeVariant = (type?: string) => { } }; -export function HomepageAlertCard({ +export function AlertCard({ alert, onDismiss, onClose, diff --git a/src/ui/Desktop/Homepage/HomepageAlertManager.tsx b/src/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertManager.tsx similarity index 94% rename from src/ui/Desktop/Homepage/HomepageAlertManager.tsx rename to src/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertManager.tsx index cab8700f..16037a07 100644 --- a/src/ui/Desktop/Homepage/HomepageAlertManager.tsx +++ b/src/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertManager.tsx @@ -1,23 +1,23 @@ import React, { useEffect, useState } from "react"; -import { HomepageAlertCard } from "./HomepageAlertCard.tsx"; +import { AlertCard } from "./AlertCard.tsx"; import { Button } from "@/components/ui/button.tsx"; import { getUserAlerts, dismissAlert } from "@/ui/main-axios.ts"; import { useTranslation } from "react-i18next"; -import type { TermixAlert } from "../../../types/index.js"; +import type { TermixAlert } from "../../../../../../types"; interface AlertManagerProps { userId: string | null; loggedIn: boolean; } -export function HomepageAlertManager({ +export function AlertManager({ userId, loggedIn, }: AlertManagerProps): React.ReactElement { const { t } = useTranslation(); const [alerts, setAlerts] = useState([]); const [currentAlertIndex, setCurrentAlertIndex] = useState(0); - const [loading, setLoading] = useState(false); + const [, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { @@ -52,7 +52,7 @@ export function HomepageAlertManager({ setAlerts(sortedAlerts); setCurrentAlertIndex(0); - } catch (err) { + } catch { const { toast } = await import("sonner"); toast.error(t("homepage.failedToLoadAlerts")); setError(t("homepage.failedToLoadAlerts")); @@ -77,7 +77,7 @@ export function HomepageAlertManager({ return Math.max(0, newAlertsLength - 1); return prevIndex; }); - } catch (err) { + } catch { setError(t("homepage.failedToDismissAlert")); } }; @@ -129,7 +129,7 @@ export function HomepageAlertManager({ return (
- { + loggedIn: boolean; +} + +interface ReleaseItem { + id: number; + title: string; + description: string; + link: string; + pubDate: string; + version: string; + isPrerelease: boolean; + isDraft: boolean; + assets: Array<{ + name: string; + size: number; + download_count: number; + download_url: string; + }>; +} + +interface RSSResponse { + feed: { + title: string; + description: string; + link: string; + updated: string; + }; + items: ReleaseItem[]; + total_count: number; + cached: boolean; + cache_age?: number; +} + +interface VersionResponse { + status: "up_to_date" | "requires_update"; + version: string; + latest_release: { + name: string; + published_at: string; + html_url: string; + }; + cached: boolean; + cache_age?: number; +} + +export function UpdateLog({ loggedIn }: UpdateLogProps) { + const { t } = useTranslation(); + const [releases, setReleases] = useState(null); + const [versionInfo, setVersionInfo] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [isOpen, setIsOpen] = useState(false); + + useEffect(() => { + if (loggedIn && isOpen) { + setLoading(true); + Promise.all([getReleasesRSS(100), getVersionInfo()]) + .then(([releasesRes, versionRes]) => { + setReleases(releasesRes); + setVersionInfo(versionRes); + setError(null); + }) + .catch(() => { + setError(t("common.failedToFetchUpdateInfo")); + }) + .finally(() => setLoading(false)); + } + }, [loggedIn, isOpen]); + + if (!loggedIn) { + return null; + } + + const formatDescription = (description: string) => { + const firstLine = description.split("\n")[0]; + return firstLine.replace(/[#*`]/g, "").replace(/\s+/g, " ").trim(); + }; + + return ( + <> + + + + +
+

+ {t("common.updatesAndReleases")} +

+ +
+ +
+ {versionInfo && versionInfo.status === "requires_update" && ( + + + {t("common.updateAvailable")} + + + {t("common.newVersionAvailable", { + version: versionInfo.version, + })} + + + )} + + {loading && ( +
+
+
+ )} + + {error && ( + + + {t("common.error")} + + + {error} + + + )} + +
+ {releases?.items.map((release) => ( +
window.open(release.link, "_blank")} + > +
+

+ {release.title} +

+ {release.isPrerelease && ( + + {t("common.preRelease")} + + )} +
+ +

+ {formatDescription(release.description)} +

+ +
+ + {new Date(release.pubDate).toLocaleDateString()} + + {release.assets.length > 0 && ( + <> + + + {release.assets.length} asset + {release.assets.length !== 1 ? "s" : ""} + + + )} +
+
+ ))} +
+ + {releases && releases.items.length === 0 && !loading && ( + + + {t("common.noReleases")} + + + {t("common.noReleasesFound")} + + + )} +
+
+
+ + ); +} diff --git a/src/ui/Desktop/Apps/Dashboard/Dashboard.tsx b/src/ui/Desktop/Apps/Dashboard/Dashboard.tsx new file mode 100644 index 00000000..ced98ced --- /dev/null +++ b/src/ui/Desktop/Apps/Dashboard/Dashboard.tsx @@ -0,0 +1,660 @@ +import React, { useEffect, useState } from "react"; +import { Auth } from "@/ui/Desktop/Authentication/Auth.tsx"; +import { UpdateLog } from "@/ui/Desktop/Apps/Dashboard/Apps/UpdateLog.tsx"; +import { AlertManager } from "@/ui/Desktop/Apps/Dashboard/Apps/Alerts/AlertManager.tsx"; +import { Button } from "@/components/ui/button.tsx"; +import { + getUserInfo, + getDatabaseHealth, + getCookie, + getUptime, + getVersionInfo, + getSSHHosts, + getTunnelStatuses, + getCredentials, + getRecentActivity, + resetRecentActivity, + getServerMetricsById, + type RecentActivityItem, +} from "@/ui/main-axios.ts"; +import { useSidebar } from "@/components/ui/sidebar.tsx"; +import { Separator } from "@/components/ui/separator.tsx"; +import { useTabs } from "@/ui/Desktop/Navigation/Tabs/TabContext.tsx"; +import { + ChartLine, + Clock, + Database, + FastForward, + History, + Key, + Network, + Server, + UserPlus, + Settings, + User, +} from "lucide-react"; +import { Status } from "@/components/ui/shadcn-io/status"; +import { BsLightning } from "react-icons/bs"; + +interface DashboardProps { + onSelectView: (view: string) => void; + isAuthenticated: boolean; + authLoading: boolean; + onAuthSuccess: (authData: { + isAdmin: boolean; + username: string | null; + userId: string | null; + }) => void; + isTopbarOpen: boolean; +} + +export function Dashboard({ + isAuthenticated, + authLoading, + onAuthSuccess, + isTopbarOpen, + onSelectView, +}: DashboardProps): React.ReactElement { + const [loggedIn, setLoggedIn] = useState(isAuthenticated); + const [isAdmin, setIsAdmin] = useState(false); + const [, setUsername] = useState(null); + const [userId, setUserId] = useState(null); + const [dbError, setDbError] = useState(null); + + // Dashboard data state + const [uptime, setUptime] = useState("0d 0h 0m"); + const [versionStatus, setVersionStatus] = useState< + "up_to_date" | "requires_update" + >("up_to_date"); + const [versionText, setVersionText] = useState("v1.8.0"); + const [dbHealth, setDbHealth] = useState<"healthy" | "error">("healthy"); + const [totalServers, setTotalServers] = useState(0); + const [totalTunnels, setTotalTunnels] = useState(0); + const [totalCredentials, setTotalCredentials] = useState(0); + const [recentActivity, setRecentActivity] = useState( + [], + ); + const [serverStats, setServerStats] = useState< + Array<{ id: number; name: string; cpu: number | null; ram: number | null }> + >([]); + + const { addTab, setCurrentTab, tabs: tabList } = useTabs(); + + let sidebarState: "expanded" | "collapsed" = "expanded"; + try { + const sidebar = useSidebar(); + sidebarState = sidebar.state; + } catch {} + + const topMarginPx = isTopbarOpen ? 74 : 26; + const leftMarginPx = sidebarState === "collapsed" ? 26 : 8; + const bottomMarginPx = 8; + + useEffect(() => { + setLoggedIn(isAuthenticated); + }, [isAuthenticated]); + + useEffect(() => { + if (isAuthenticated) { + if (getCookie("jwt")) { + getUserInfo() + .then((meRes) => { + setIsAdmin(!!meRes.is_admin); + setUsername(meRes.username || null); + setUserId(meRes.userId || null); + setDbError(null); + }) + .catch((err) => { + setIsAdmin(false); + setUsername(null); + setUserId(null); + + const errorCode = err?.response?.data?.code; + if (errorCode === "SESSION_EXPIRED") { + console.warn("Session expired - please log in again"); + setDbError("Session expired - please log in again"); + } else { + setDbError(null); + } + }); + + getDatabaseHealth() + .then(() => { + setDbError(null); + }) + .catch((err) => { + if (err?.response?.data?.error?.includes("Database")) { + setDbError( + "Could not connect to the database. Please try again later.", + ); + } + }); + } + } + }, [isAuthenticated]); + + // Fetch dashboard data + useEffect(() => { + if (!loggedIn) return; + + const fetchDashboardData = async () => { + try { + // Fetch uptime + const uptimeInfo = await getUptime(); + setUptime(uptimeInfo.formatted); + + // Fetch version info + const versionInfo = await getVersionInfo(); + setVersionText(`v${versionInfo.localVersion}`); + setVersionStatus(versionInfo.status || "up_to_date"); + + // Fetch database health + try { + await getDatabaseHealth(); + setDbHealth("healthy"); + } catch { + setDbHealth("error"); + } + + // Fetch total counts + const hosts = await getSSHHosts(); + setTotalServers(hosts.length); + + // Count total tunnels across all hosts + let totalTunnelsCount = 0; + for (const host of hosts) { + if (host.tunnelConnections) { + try { + const tunnelConnections = JSON.parse(host.tunnelConnections); + if (Array.isArray(tunnelConnections)) { + totalTunnelsCount += tunnelConnections.length; + } + } catch { + // Ignore parse errors + } + } + } + setTotalTunnels(totalTunnelsCount); + + const credentials = await getCredentials(); + setTotalCredentials(credentials.length); + + // Fetch recent activity (35 items) + const activity = await getRecentActivity(35); + setRecentActivity(activity); + + // Fetch server stats for first 5 servers + const serversWithStats = await Promise.all( + hosts.slice(0, 5).map(async (host: { id: number; name: string }) => { + try { + const metrics = await getServerMetricsById(host.id); + return { + id: host.id, + name: host.name || `Host ${host.id}`, + cpu: metrics.cpu.percent, + ram: metrics.memory.percent, + }; + } catch { + return { + id: host.id, + name: host.name || `Host ${host.id}`, + cpu: null, + ram: null, + }; + } + }), + ); + setServerStats(serversWithStats); + } catch (error) { + console.error("Failed to fetch dashboard data:", error); + } + }; + + fetchDashboardData(); + + // Refresh every 30 seconds + const interval = setInterval(fetchDashboardData, 30000); + return () => clearInterval(interval); + }, [loggedIn]); + + // Handler for resetting recent activity + const handleResetActivity = async () => { + try { + await resetRecentActivity(); + setRecentActivity([]); + } catch (error) { + console.error("Failed to reset activity:", error); + } + }; + + // Handler for opening a recent activity item + const handleActivityClick = (item: RecentActivityItem) => { + // Find the host and open appropriate tab + getSSHHosts().then((hosts) => { + const host = hosts.find((h: { id: number }) => h.id === item.hostId); + if (!host) return; + + if (item.type === "terminal") { + addTab({ + type: "terminal", + title: item.hostName, + hostConfig: host, + }); + } else if (item.type === "file_manager") { + addTab({ + type: "file_manager", + title: item.hostName, + hostConfig: host, + }); + } + }); + }; + + // Quick Actions handlers + const handleAddHost = () => { + const sshManagerTab = tabList.find((t) => t.type === "ssh_manager"); + if (sshManagerTab) { + setCurrentTab(sshManagerTab.id); + } else { + const id = addTab({ + type: "ssh_manager", + title: "Host Manager", + initialTab: "add_host", + }); + setCurrentTab(id); + } + }; + + const handleAddCredential = () => { + const sshManagerTab = tabList.find((t) => t.type === "ssh_manager"); + if (sshManagerTab) { + setCurrentTab(sshManagerTab.id); + } else { + const id = addTab({ + type: "ssh_manager", + title: "Host Manager", + initialTab: "add_credential", + }); + setCurrentTab(id); + } + }; + + const handleOpenAdminSettings = () => { + const adminTab = tabList.find((t) => t.type === "admin"); + if (adminTab) { + setCurrentTab(adminTab.id); + } else { + const id = addTab({ type: "admin", title: "Admin Settings" }); + setCurrentTab(id); + } + }; + + const handleOpenUserProfile = () => { + const userProfileTab = tabList.find((t) => t.type === "user_profile"); + if (userProfileTab) { + setCurrentTab(userProfileTab.id); + } else { + const id = addTab({ type: "user_profile", title: "User Profile" }); + setCurrentTab(id); + } + }; + + return ( + <> + {!loggedIn ? ( +
+ +
+ ) : ( +
+
+
+
Dashboard
+
+ + + + +
+
+ + + +
+
+
+
+

+ + Server Overview +

+
+
+
+ +

Version

+
+ +
+

+ {versionText} +

+ + +
+
+ +
+
+ +

Uptime

+
+ +
+

+ {uptime} +

+
+
+ +
+
+ +

Database

+
+ +
+

+ {dbHealth} +

+
+
+
+
+
+
+ +

Total Servers

+
+

+ {totalServers} +

+
+
+
+ +

Total Tunnels

+
+

+ {totalTunnels} +

+
+
+
+
+
+ +

Total Credentials

+
+

+ {totalCredentials} +

+
+
+
+
+
+
+
+

+ + Recent Activity +

+ +
+
+ {recentActivity.length === 0 ? ( +

+ No recent activity +

+ ) : ( + recentActivity.map((item) => ( + + )) + )} +
+
+
+
+
+
+
+

+ + Quick Actions +

+
+ + + {isAdmin && ( + + )} + +
+
+
+
+
+

+ + Server Stats +

+
+ {serverStats.length === 0 ? ( +

+ No server data available +

+ ) : ( + serverStats.map((server) => ( + + )) + )} +
+
+
+
+
+
+
+ )} + + + + ); +} diff --git a/src/ui/Desktop/Homepage/DragIndicator.tsx b/src/ui/Desktop/Apps/File Manager/DragIndicator.tsx similarity index 100% rename from src/ui/Desktop/Homepage/DragIndicator.tsx rename to src/ui/Desktop/Apps/File Manager/DragIndicator.tsx diff --git a/src/ui/Desktop/Apps/File Manager/FileManager.tsx b/src/ui/Desktop/Apps/File Manager/FileManager.tsx index ea991003..bb1b5842 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManager.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManager.tsx @@ -14,6 +14,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { toast } from "sonner"; import { useTranslation } from "react-i18next"; +import { TOTPDialog } from "@/ui/components/TOTPDialog"; import { Upload, FolderPlus, @@ -22,8 +23,6 @@ import { Search, Grid3X3, List, - Eye, - Settings, } from "lucide-react"; import { TerminalWindow } from "./components/TerminalWindow"; import type { SSHHost, FileItem } from "../../../types/index.js"; @@ -38,6 +37,7 @@ import { renameSSHItem, moveSSHItem, connectSSH, + verifySSHTOTP, getSSHStatus, keepSSHAlive, identifySSHSymlink, @@ -47,6 +47,7 @@ import { removeRecentFile, addFolderShortcut, getPinnedFiles, + logActivity, } from "@/ui/main-axios.ts"; import type { SidebarItem } from "./FileManagerSidebar"; @@ -85,9 +86,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { const { t } = useTranslation(); const { confirmWithToast } = useConfirmation(); - const [currentHost, setCurrentHost] = useState( - initialHost || null, - ); + const [currentHost] = useState(initialHost || null); const [currentPath, setCurrentPath] = useState( initialHost?.defaultPath || "/", ); @@ -98,6 +97,9 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { const [searchQuery, setSearchQuery] = useState(""); const [lastRefreshTime, setLastRefreshTime] = useState(0); const [viewMode, setViewMode] = useState<"grid" | "list">("grid"); + const [totpRequired, setTotpRequired] = useState(false); + const [totpSessionId, setTotpSessionId] = useState(null); + const [totpPrompt, setTotpPrompt] = useState(""); const [pinnedFiles, setPinnedFiles] = useState>(new Set()); const [sidebarRefreshTrigger, setSidebarRefreshTrigger] = useState(0); const [isClosing, setIsClosing] = useState(false); @@ -140,10 +142,9 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { const [createIntent, setCreateIntent] = useState(null); const [editingFile, setEditingFile] = useState(null); - const { selectedFiles, selectFile, selectAll, clearSelection, setSelection } = - useFileSelection(); + const { selectedFiles, clearSelection, setSelection } = useFileSelection(); - const { isDragging, dragHandlers } = useDragAndDrop({ + const { dragHandlers } = useDragAndDrop({ onFilesDropped: handleFilesDropped, onError: (error) => toast.error(error), maxFileSize: 5120, @@ -288,8 +289,25 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { userId: currentHost.userId, }); + if (result?.requires_totp) { + setTotpRequired(true); + setTotpSessionId(sessionId); + setTotpPrompt(result.prompt || "Verification code:"); + setIsLoading(false); + return; + } + setSshSessionId(sessionId); + // Log activity for recent connections + if (currentHost?.id) { + const hostName = + currentHost.name || `${currentHost.username}@${currentHost.ip}`; + logActivity("file_manager", currentHost.id, hostName).catch((err) => { + console.warn("Failed to log file manager activity:", err); + }); + } + try { const response = await listSSHFiles(sessionId, currentPath); const files = Array.isArray(response) @@ -298,10 +316,10 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { setFiles(files); clearSelection(); initialLoadDoneRef.current = true; - } catch (dirError: any) { + } catch (dirError: unknown) { console.error("Failed to load initial directory:", dirError); } - } catch (error: any) { + } catch (error: unknown) { console.error("SSH connection failed:", error); handleCloseWithError( t("fileManager.failedToConnect") + ": " + (error.message || error), @@ -340,7 +358,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { setFiles(files); clearSelection(); - } catch (error: any) { + } catch (error: unknown) { if (currentLoadingPathRef.current === path) { console.error("Failed to load directory:", error); @@ -522,7 +540,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { t("fileManager.fileUploadedSuccessfully", { name: file.name }), ); handleRefreshDirectory(); - } catch (error: any) { + } catch (error: unknown) { toast.dismiss(progressToast); if ( @@ -571,7 +589,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { t("fileManager.fileDownloadedSuccessfully", { name: file.name }), ); } - } catch (error: any) { + } catch (error: unknown) { if ( error.message?.includes("connection") || error.message?.includes("established") @@ -652,7 +670,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { ); handleRefreshDirectory(); clearSelection(); - } catch (error: any) { + } catch (error: unknown) { if ( error.message?.includes("connection") || error.message?.includes("established") @@ -706,28 +724,24 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { } try { - let currentSessionId = sshSessionId; - try { - const status = await getSSHStatus(currentSessionId); - if (!status.connected) { - const result = await connectSSH(currentSessionId, { - hostId: currentHost.id, - host: currentHost.ip, - port: currentHost.port, - username: currentHost.username, - authType: currentHost.authType, - password: currentHost.password, - key: currentHost.key, - keyPassword: currentHost.keyPassword, - credentialId: currentHost.credentialId, - }); + const currentSessionId = sshSessionId; + const status = await getSSHStatus(currentSessionId); + if (!status.connected) { + const result = await connectSSH(currentSessionId, { + hostId: currentHost.id, + host: currentHost.ip, + port: currentHost.port, + username: currentHost.username, + authType: currentHost.authType, + password: currentHost.password, + key: currentHost.key, + keyPassword: currentHost.keyPassword, + credentialId: currentHost.credentialId, + }); - if (!result.success) { - throw new Error(t("fileManager.failedToReconnectSSH")); - } + if (!result.success) { + throw new Error(t("fileManager.failedToReconnectSSH")); } - } catch (sessionErr) { - throw sessionErr; } const symlinkInfo = await identifySSHSymlink(currentSessionId, file.path); @@ -766,7 +780,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { component: createWindowComponent, }); } - } catch (error: any) { + } catch (error: unknown) { toast.error( error?.response?.data?.error || error?.message || @@ -775,7 +789,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { } }; - async function handleFileOpen(file: FileItem, editMode: boolean = false) { + async function handleFileOpen(file: FileItem) { if (file.type === "directory") { setCurrentPath(file.path); } else if (file.type === "link") { @@ -825,14 +839,6 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { } } - function handleFileEdit(file: FileItem) { - handleFileOpen(file, true); - } - - function handleFileView(file: FileItem) { - handleFileOpen(file, false); - } - function handleContextMenu(event: React.MouseEvent, file?: FileItem) { event.preventDefault(); @@ -905,7 +911,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { successCount++; } } - } catch (error: any) { + } catch (error: unknown) { console.error(`Failed to ${operation} file ${file.name}:`, error); toast.error( t("fileManager.operationFailed", { @@ -1006,7 +1012,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { if (operation === "cut") { setClipboard(null); } - } catch (error: any) { + } catch (error: unknown) { toast.error( `${t("fileManager.pasteFailed")}: ${error.message || t("fileManager.unknownError")}`, ); @@ -1041,7 +1047,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { currentHost?.userId?.toString(), ); successCount++; - } catch (error: any) { + } catch (error: unknown) { console.error( `Failed to delete copied file ${copiedFile.targetName}:`, error, @@ -1083,7 +1089,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { currentHost?.userId?.toString(), ); successCount++; - } catch (error: any) { + } catch (error: unknown) { console.error( `Failed to move back file ${movedFile.targetName}:`, error, @@ -1123,7 +1129,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { } handleRefreshDirectory(); - } catch (error: any) { + } catch (error: unknown) { toast.error( `${t("fileManager.undoOperationFailed")}: ${error.message || t("fileManager.unknownError")}`, ); @@ -1195,7 +1201,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { setCreateIntent(null); handleRefreshDirectory(); - } catch (error: any) { + } catch (error: unknown) { console.error("Create failed:", error); toast.error(t("fileManager.failedToCreateItem")); } @@ -1224,7 +1230,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { ); setEditingFile(null); handleRefreshDirectory(); - } catch (error: any) { + } catch (error: unknown) { console.error("Rename failed:", error); toast.error(t("fileManager.failedToRenameItem")); } @@ -1238,6 +1244,56 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { setEditingFile(null); } + async function handleTotpSubmit(code: string) { + if (!totpSessionId || !code) return; + + try { + setIsLoading(true); + const result = await verifySSHTOTP(totpSessionId, code); + + if (result?.status === "success") { + setTotpRequired(false); + setTotpPrompt(""); + setSshSessionId(totpSessionId); + setTotpSessionId(null); + + // Log activity for recent connections + if (currentHost?.id) { + const hostName = + currentHost.name || `${currentHost.username}@${currentHost.ip}`; + logActivity("file_manager", currentHost.id, hostName).catch((err) => { + console.warn("Failed to log file manager activity:", err); + }); + } + + try { + const response = await listSSHFiles(totpSessionId, currentPath); + const files = Array.isArray(response) + ? response + : response?.files || []; + setFiles(files); + clearSelection(); + initialLoadDoneRef.current = true; + toast.success(t("fileManager.connectedSuccessfully")); + } catch (dirError: unknown) { + console.error("Failed to load initial directory:", dirError); + } + } + } catch (error: unknown) { + console.error("TOTP verification failed:", error); + toast.error(t("fileManager.totpVerificationFailed")); + } finally { + setIsLoading(false); + } + } + + function handleTotpCancel() { + setTotpRequired(false); + setTotpPrompt(""); + setTotpSessionId(null); + if (onClose) onClose(); + } + function generateUniqueName( baseName: string, type: "file" | "directory", @@ -1290,7 +1346,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { movedItems.push(file.name); successCount++; } - } catch (error: any) { + } catch (error: unknown) { console.error(`Failed to move file ${file.name}:`, error); toast.error( t("fileManager.moveFileFailed", { name: file.name }) + @@ -1301,18 +1357,16 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { } if (successCount > 0) { - const movedFiles = draggedFiles - .slice(0, successCount) - .map((file, index) => { - const targetPath = targetFolder.path.endsWith("/") - ? `${targetFolder.path}${file.name}` - : `${targetFolder.path}/${file.name}`; - return { - originalPath: file.path, - targetPath: targetPath, - targetName: file.name, - }; - }); + const movedFiles = draggedFiles.slice(0, successCount).map((file) => { + const targetPath = targetFolder.path.endsWith("/") + ? `${targetFolder.path}${file.name}` + : `${targetFolder.path}/${file.name}`; + return { + originalPath: file.path, + targetPath: targetPath, + targetName: file.name, + }; + }); const undoAction: UndoAction = { type: "cut", @@ -1338,7 +1392,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { handleRefreshDirectory(); clearSelection(); } - } catch (error: any) { + } catch (error: unknown) { console.error("Drag move operation failed:", error); toast.error(t("fileManager.moveOperationFailed") + ": " + error.message); } @@ -1409,7 +1463,7 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { await dragToDesktop.dragFilesToDesktop(files); } } - } catch (error: any) { + } catch (error: unknown) { console.error("Drag to desktop failed:", error); toast.error( t("fileManager.dragFailed") + @@ -1504,7 +1558,9 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { try { const pinnedData = await getPinnedFiles(currentHost.id); - const pinnedPaths = new Set(pinnedData.map((item: any) => item.path)); + const pinnedPaths = new Set( + pinnedData.map((item: Record) => item.path), + ); setPinnedFiles(pinnedPaths); } catch (error) { console.error("Failed to load pinned files:", error); @@ -1806,6 +1862,13 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { />
+ + ); } diff --git a/src/ui/Desktop/Apps/File Manager/FileManagerContextMenu.tsx b/src/ui/Desktop/Apps/File Manager/FileManagerContextMenu.tsx index 8867c176..6dfdc3af 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManagerContextMenu.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManagerContextMenu.tsx @@ -13,8 +13,6 @@ import { RefreshCw, Clipboard, Eye, - Share, - ExternalLink, Terminal, Play, Star, @@ -190,7 +188,6 @@ export function FileManagerContextMenu({ const isSingleFile = files.length === 1; const isMultipleFiles = files.length > 1; const hasFiles = files.some((f) => f.type === "file"); - const hasDirectories = files.some((f) => f.type === "directory"); const hasExecutableFiles = files.some( (f) => f.type === "file" && f.executable, ); diff --git a/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx b/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx index 039f75eb..154b0aab 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx @@ -166,7 +166,6 @@ const getFileIcon = (file: FileItem, viewMode: "grid" | "list" = "grid") => { export function FileManagerGrid({ files, selectedFiles, - onFileSelect, onFileOpen, onSelectionChange, currentPath, @@ -188,7 +187,6 @@ export function FileManagerGrid({ onUndo, onFileDrop, onFileDiff, - onSystemDragStart, onSystemDragEnd, hasClipboard, createIntent, @@ -327,7 +325,6 @@ export function FileManagerGrid({ dragState.files[0].type === "file" ) { onFileDiff?.(dragState.files[0], targetFile); - } else { } setDragState({ type: "none", files: [], counter: 0 }); @@ -429,16 +426,6 @@ export function FileManagerGrid({ setIsEditingPath(false); }; - const handlePathInputKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { - e.preventDefault(); - confirmEditingPath(); - } else if (e.key === "Escape") { - e.preventDefault(); - cancelEditingPath(); - } - }; - useEffect(() => { if (!isEditingPath) { setEditPathValue(currentPath); @@ -458,8 +445,6 @@ export function FileManagerGrid({ type: "external", counter: prev.counter + 1, })); - if (e.dataTransfer.items && e.dataTransfer.items.length > 0) { - } } }, [dragState.type], @@ -620,7 +605,7 @@ export function FileManagerGrid({ ); useEffect(() => { - const handleGlobalMouseUp = (e: MouseEvent) => { + const handleGlobalMouseUp = () => { if (isSelecting) { setIsSelecting(false); setSelectionStart(null); diff --git a/src/ui/Desktop/Apps/File Manager/FileManagerSidebar.tsx b/src/ui/Desktop/Apps/File Manager/FileManagerSidebar.tsx index 763f4dee..fc63779d 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManagerSidebar.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManagerSidebar.tsx @@ -23,6 +23,35 @@ import { } from "@/ui/main-axios.ts"; import { toast } from "sonner"; +interface RecentFileData { + id: number; + name: string; + path: string; + lastOpened?: string; + [key: string]: unknown; +} + +interface PinnedFileData { + id: number; + name: string; + path: string; + [key: string]: unknown; +} + +interface ShortcutData { + id: number; + name: string; + path: string; + [key: string]: unknown; +} + +interface DirectoryItemData { + name: string; + path: string; + type: string; + [key: string]: unknown; +} + export interface SidebarItem { id: string; name: string; @@ -37,7 +66,6 @@ interface FileManagerSidebarProps { currentHost: SSHHost; currentPath: string; onPathChange: (path: string) => void; - onLoadDirectory?: (path: string) => void; onFileOpen?: (file: SidebarItem) => void; sshSessionId?: string; refreshTrigger?: number; @@ -47,7 +75,6 @@ export function FileManagerSidebar({ currentHost, currentPath, onPathChange, - onLoadDirectory, onFileOpen, sshSessionId, refreshTrigger, @@ -88,31 +115,37 @@ export function FileManagerSidebar({ try { const recentData = await getRecentFiles(currentHost.id); - const recentItems = recentData.slice(0, 5).map((item: any) => ({ - id: `recent-${item.id}`, - name: item.name, - path: item.path, - type: "recent" as const, - lastAccessed: item.lastOpened, - })); + const recentItems = (recentData as RecentFileData[]) + .slice(0, 5) + .map((item: RecentFileData) => ({ + id: `recent-${item.id}`, + name: item.name, + path: item.path, + type: "recent" as const, + lastAccessed: item.lastOpened, + })); setRecentItems(recentItems); const pinnedData = await getPinnedFiles(currentHost.id); - const pinnedItems = pinnedData.map((item: any) => ({ - id: `pinned-${item.id}`, - name: item.name, - path: item.path, - type: "pinned" as const, - })); + const pinnedItems = (pinnedData as PinnedFileData[]).map( + (item: PinnedFileData) => ({ + id: `pinned-${item.id}`, + name: item.name, + path: item.path, + type: "pinned" as const, + }), + ); setPinnedItems(pinnedItems); const shortcutData = await getFolderShortcuts(currentHost.id); - const shortcutItems = shortcutData.map((item: any) => ({ - id: `shortcut-${item.id}`, - name: item.name, - path: item.path, - type: "shortcut" as const, - })); + const shortcutItems = (shortcutData as ShortcutData[]).map( + (item: ShortcutData) => ({ + id: `shortcut-${item.id}`, + name: item.name, + path: item.path, + type: "shortcut" as const, + }), + ); setShortcuts(shortcutItems); } catch (error) { console.error("Failed to load quick access data:", error); @@ -230,12 +263,12 @@ export function FileManagerSidebar({ try { const response = await listSSHFiles(sshSessionId, "/"); - const rootFiles = response.files || []; + const rootFiles = (response.files || []) as DirectoryItemData[]; const rootFolders = rootFiles.filter( - (item: any) => item.type === "directory", + (item: DirectoryItemData) => item.type === "directory", ); - const rootTreeItems = rootFolders.map((folder: any) => ({ + const rootTreeItems = rootFolders.map((folder: DirectoryItemData) => ({ id: `folder-${folder.name}`, name: folder.name, path: folder.path, @@ -298,12 +331,12 @@ export function FileManagerSidebar({ try { const subResponse = await listSSHFiles(sshSessionId, folderPath); - const subFiles = subResponse.files || []; + const subFiles = (subResponse.files || []) as DirectoryItemData[]; const subFolders = subFiles.filter( - (item: any) => item.type === "directory", + (item: DirectoryItemData) => item.type === "directory", ); - const subTreeItems = subFolders.map((folder: any) => ({ + const subTreeItems = subFolders.map((folder: DirectoryItemData) => ({ id: `folder-${folder.path.replace(/\//g, "-")}`, name: folder.name, path: folder.path, diff --git a/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx b/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx index e9312924..70cf8d3a 100644 --- a/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx @@ -61,23 +61,19 @@ export function DiffViewer({ userId: sshHost.userId, }); } - } catch (error) { - try { - await connectSSH(sshSessionId, { - hostId: sshHost.id, - ip: sshHost.ip, - port: sshHost.port, - username: sshHost.username, - password: sshHost.password, - sshKey: sshHost.key, - keyPassword: sshHost.keyPassword, - authType: sshHost.authType, - credentialId: sshHost.credentialId, - userId: sshHost.userId, - }); - } catch (reconnectError) { - throw reconnectError; - } + } catch { + await connectSSH(sshSessionId, { + hostId: sshHost.id, + ip: sshHost.ip, + port: sshHost.port, + username: sshHost.username, + password: sshHost.password, + sshKey: sshHost.key, + keyPassword: sshHost.keyPassword, + authType: sshHost.authType, + credentialId: sshHost.credentialId, + userId: sshHost.userId, + }); } }; @@ -100,15 +96,19 @@ export function DiffViewer({ setContent1(response1.content || ""); setContent2(response2.content || ""); - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to load files for diff:", error); - const errorData = error?.response?.data; + const err = error as { + message?: string; + response?: { data?: { tooLarge?: boolean; error?: string } }; + }; + const errorData = err?.response?.data; if (errorData?.tooLarge) { setError(t("fileManager.fileTooLarge", { error: errorData.error })); } else if ( - error.message?.includes("connection") || - error.message?.includes("established") + err.message?.includes("connection") || + err.message?.includes("established") ) { setError( t("fileManager.sshConnectionFailed", { @@ -121,9 +121,7 @@ export function DiffViewer({ setError( t("fileManager.loadFileFailed", { error: - error.message || - errorData?.error || - t("fileManager.unknownError"), + err.message || errorData?.error || t("fileManager.unknownError"), }), ); } @@ -161,12 +159,13 @@ export function DiffViewer({ t("fileManager.downloadFileSuccess", { name: file.name }), ); } - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to download file:", error); + const err = error as { message?: string }; toast.error( t("fileManager.downloadFileFailed") + ": " + - (error.message || t("fileManager.unknownError")), + (err.message || t("fileManager.unknownError")), ); } }; diff --git a/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx b/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx index 5d26e07b..b24be004 100644 --- a/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/DraggableWindow.tsx @@ -1,6 +1,6 @@ import React, { useState, useRef, useCallback, useEffect } from "react"; import { cn } from "@/lib/utils"; -import { Minus, Square, X, Maximize2, Minimize2 } from "lucide-react"; +import { Minus, X, Maximize2, Minimize2 } from "lucide-react"; import { useTranslation } from "react-i18next"; interface DraggableWindowProps { diff --git a/src/ui/Desktop/Apps/File Manager/components/FileViewer.tsx b/src/ui/Desktop/Apps/File Manager/components/FileViewer.tsx index 1a3cb109..914ad304 100644 --- a/src/ui/Desktop/Apps/File Manager/components/FileViewer.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/FileViewer.tsx @@ -60,7 +60,6 @@ import { import { autocompletion, completionKeymap } from "@codemirror/autocomplete"; import { PhotoProvider, PhotoView } from "react-photo-view"; import "react-photo-view/dist/react-photo-view.css"; -import ReactPlayer from "react-player"; import AudioPlayer from "react-h5-audio-player"; import "react-h5-audio-player/lib/styles.css"; import ReactMarkdown from "react-markdown"; @@ -290,7 +289,7 @@ function getLanguageExtension(filename: string) { return language ? loadLanguage(language) : null; } -function formatFileSize(bytes?: number, t?: any): string { +function formatFileSize(bytes?: number, t?: (key: string) => string): string { if (!bytes) return t ? t("fileManager.unknownSize") : "Unknown size"; const sizes = ["B", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(1024)); @@ -311,9 +310,7 @@ export function FileViewer({ }: FileViewerProps) { const { t } = useTranslation(); const [editedContent, setEditedContent] = useState(content); - const [originalContent, setOriginalContent] = useState( - savedContent || content, - ); + const [, setOriginalContent] = useState(savedContent || content); const [hasChanges, setHasChanges] = useState(false); const [showLargeFileWarning, setShowLargeFileWarning] = useState(false); const [forceShowAsText, setForceShowAsText] = useState(false); @@ -326,7 +323,9 @@ export function FileViewer({ const [pdfScale, setPdfScale] = useState(1.2); const [pdfError, setPdfError] = useState(false); const [markdownEditMode, setMarkdownEditMode] = useState(false); - const editorRef = useRef(null); + const editorRef = useRef<{ + view?: { dispatch: (transaction: unknown) => void }; + } | null>(null); const fileTypeInfo = getFileType(file.name); @@ -975,13 +974,7 @@ export function FileViewer({ { - const audio = e.currentTarget; + onLoadedMetadata={() => { if (onMediaDimensionsChange) { onMediaDimensionsChange({ width: 600, diff --git a/src/ui/Desktop/Apps/File Manager/components/FileWindow.tsx b/src/ui/Desktop/Apps/File Manager/components/FileWindow.tsx index cd18e164..1075775d 100644 --- a/src/ui/Desktop/Apps/File Manager/components/FileWindow.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/FileWindow.tsx @@ -56,7 +56,7 @@ export function FileWindow({ initialY = 100, onFileNotFound, }: FileWindowProps) { - const { closeWindow, maximizeWindow, focusWindow, updateWindow, windows } = + const { closeWindow, maximizeWindow, focusWindow, windows } = useWindowManager(); const { t } = useTranslation(); @@ -157,28 +157,40 @@ export function FileWindow({ const extension = file.name.split(".").pop()?.toLowerCase(); setIsEditable(!mediaExtensions.includes(extension || "")); - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to load file:", error); - const errorData = error?.response?.data; + const err = error as { + message?: string; + isFileNotFound?: boolean; + response?: { + status?: number; + data?: { + tooLarge?: boolean; + error?: string; + fileNotFound?: boolean; + }; + }; + }; + const errorData = err?.response?.data; if (errorData?.tooLarge) { toast.error(`File too large: ${errorData.error}`, { duration: 10000, }); } else if ( - error.message?.includes("connection") || - error.message?.includes("established") + err.message?.includes("connection") || + err.message?.includes("established") ) { toast.error( `SSH connection failed. Please check your connection to ${sshHost.name} (${sshHost.ip}:${sshHost.port})`, ); } else { const errorMessage = - errorData?.error || error.message || "Unknown error"; + errorData?.error || err.message || "Unknown error"; const isFileNotFound = - (error as any).isFileNotFound || + err.isFileNotFound || errorData?.fileNotFound || - error.response?.status === 404 || + err.response?.status === 404 || errorMessage.includes("File not found") || errorMessage.includes("No such file or directory") || errorMessage.includes("cannot access") || @@ -229,10 +241,11 @@ export function FileWindow({ const contentSize = new Blob([fileContent]).size; file.size = contentSize; } - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to load file content:", error); + const err = error as { message?: string }; toast.error( - `${t("fileManager.failedToLoadFile")}: ${error.message || t("fileManager.unknownError")}`, + `${t("fileManager.failedToLoadFile")}: ${err.message || t("fileManager.unknownError")}`, ); } finally { setIsLoading(false); @@ -258,19 +271,20 @@ export function FileWindow({ } toast.success(t("fileManager.fileSavedSuccessfully")); - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to save file:", error); + const err = error as { message?: string }; if ( - error.message?.includes("connection") || - error.message?.includes("established") + err.message?.includes("connection") || + err.message?.includes("established") ) { toast.error( `SSH connection failed. Please check your connection to ${sshHost.name} (${sshHost.ip}:${sshHost.port})`, ); } else { toast.error( - `${t("fileManager.failedToSaveFile")}: ${error.message || t("fileManager.unknownError")}`, + `${t("fileManager.failedToSaveFile")}: ${err.message || t("fileManager.unknownError")}`, ); } } finally { @@ -335,19 +349,20 @@ export function FileWindow({ toast.success(t("fileManager.fileDownloadedSuccessfully")); } - } catch (error: any) { + } catch (error: unknown) { console.error("Failed to download file:", error); + const err = error as { message?: string }; if ( - error.message?.includes("connection") || - error.message?.includes("established") + err.message?.includes("connection") || + err.message?.includes("established") ) { toast.error( `SSH connection failed. Please check your connection to ${sshHost.name} (${sshHost.ip}:${sshHost.port})`, ); } else { toast.error( - `Failed to download file: ${error.message || "Unknown error"}`, + `Failed to download file: ${err.message || "Unknown error"}`, ); } } diff --git a/src/ui/Desktop/Apps/File Manager/components/TerminalWindow.tsx b/src/ui/Desktop/Apps/File Manager/components/TerminalWindow.tsx index 880ab5e8..7f32de01 100644 --- a/src/ui/Desktop/Apps/File Manager/components/TerminalWindow.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/TerminalWindow.tsx @@ -36,11 +36,19 @@ export function TerminalWindow({ executeCommand, }: TerminalWindowProps) { const { t } = useTranslation(); - const { closeWindow, minimizeWindow, maximizeWindow, focusWindow, windows } = + const { closeWindow, maximizeWindow, focusWindow, windows } = useWindowManager(); - const terminalRef = React.useRef(null); + const terminalRef = React.useRef<{ fit?: () => void } | null>(null); const resizeTimeoutRef = React.useRef(null); + React.useEffect(() => { + return () => { + if (resizeTimeoutRef.current) { + clearTimeout(resizeTimeoutRef.current); + } + }; + }, []); + const currentWindow = windows.find((w) => w.id === windowId); if (!currentWindow) { return null; @@ -50,10 +58,6 @@ export function TerminalWindow({ closeWindow(windowId); }; - const handleMinimize = () => { - minimizeWindow(windowId); - }; - const handleMaximize = () => { maximizeWindow(windowId); }; @@ -74,14 +78,6 @@ export function TerminalWindow({ }, 100); }; - React.useEffect(() => { - return () => { - if (resizeTimeoutRef.current) { - clearTimeout(resizeTimeoutRef.current); - } - }; - }, []); - const terminalTitle = executeCommand ? t("terminal.runTitle", { host: hostConfig.name, command: executeCommand }) : initialPath diff --git a/src/ui/Desktop/Apps/File Manager/components/WindowManager.tsx b/src/ui/Desktop/Apps/File Manager/components/WindowManager.tsx index ce200d64..6318cb74 100644 --- a/src/ui/Desktop/Apps/File Manager/components/WindowManager.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/WindowManager.tsx @@ -1,3 +1,4 @@ +/* eslint-disable react-refresh/only-export-components */ import React, { useState, useCallback, useRef } from "react"; export interface WindowInstance { diff --git a/src/ui/Desktop/Apps/Host Manager/HostManager.tsx b/src/ui/Desktop/Apps/Host Manager/HostManager.tsx index 34db6aa1..2c8cb529 100644 --- a/src/ui/Desktop/Apps/Host Manager/HostManager.tsx +++ b/src/ui/Desktop/Apps/Host Manager/HostManager.tsx @@ -15,14 +15,18 @@ import { useTranslation } from "react-i18next"; import type { SSHHost, HostManagerProps } from "../../../types/index"; export function HostManager({ - onSelectView, isTopbarOpen, + initialTab = "host_viewer", }: HostManagerProps): React.ReactElement { const { t } = useTranslation(); - const [activeTab, setActiveTab] = useState("host_viewer"); + const [activeTab, setActiveTab] = useState(initialTab); const [editingHost, setEditingHost] = useState(null); - const [editingCredential, setEditingCredential] = useState(null); + const [editingCredential, setEditingCredential] = useState<{ + id: number; + name?: string; + username: string; + } | null>(null); const { state: sidebarState } = useSidebar(); const handleEditHost = (host: SSHHost) => { @@ -30,12 +34,16 @@ export function HostManager({ setActiveTab("add_host"); }; - const handleFormSubmit = (updatedHost?: SSHHost) => { + const handleFormSubmit = () => { setEditingHost(null); setActiveTab("host_viewer"); }; - const handleEditCredential = (credential: any) => { + const handleEditCredential = (credential: { + id: number; + name?: string; + username: string; + }) => { setEditingCredential(credential); setActiveTab("add_credential"); }; diff --git a/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx b/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx index 0fe881ef..df38275f 100644 --- a/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx +++ b/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx @@ -38,6 +38,9 @@ import { CredentialSelector } from "@/ui/Desktop/Apps/Credentials/CredentialSele import CodeMirror from "@uiw/react-codemirror"; import { oneDark } from "@codemirror/theme-one-dark"; import { EditorView } from "@codemirror/view"; +import type { StatsConfig } from "@/types/stats-widgets"; +import { DEFAULT_STATS_CONFIG } from "@/types/stats-widgets"; +import { Checkbox } from "@/components/ui/checkbox.tsx"; interface SSHHost { id: number; @@ -57,7 +60,15 @@ interface SSHHost { enableTunnel: boolean; enableFileManager: boolean; defaultPath: string; - tunnelConnections: any[]; + tunnelConnections: Array<{ + sourcePort: number; + endpointPort: number; + endpointHost: string; + maxRetries: number; + retryInterval: number; + autoStart: boolean; + }>; + statsConfig?: StatsConfig; createdAt: string; updatedAt: string; credentialId?: number; @@ -73,11 +84,11 @@ export function HostManagerEditor({ onFormSubmit, }: SSHManagerHostEditorProps) { const { t } = useTranslation(); - const [hosts, setHosts] = useState([]); const [folders, setFolders] = useState([]); const [sshConfigurations, setSshConfigurations] = useState([]); - const [credentials, setCredentials] = useState([]); - const [loading, setLoading] = useState(true); + const [credentials, setCredentials] = useState< + Array<{ id: number; username: string; authType: string }> + >([]); const [authTab, setAuthTab] = useState<"password" | "key" | "credential">( "password", @@ -92,12 +103,10 @@ export function HostManagerEditor({ useEffect(() => { const fetchData = async () => { try { - setLoading(true); const [hostsData, credentialsData] = await Promise.all([ getSSHHosts(), getCredentials(), ]); - setHosts(hostsData); setCredentials(credentialsData); const uniqueFolders = [ @@ -118,9 +127,8 @@ export function HostManagerEditor({ setFolders(uniqueFolders); setSshConfigurations(uniqueConfigurations); - } catch (error) { - } finally { - setLoading(false); + } catch { + // Failed to load hosts data } }; @@ -130,9 +138,7 @@ export function HostManagerEditor({ useEffect(() => { const handleCredentialChange = async () => { try { - setLoading(true); const hostsData = await getSSHHosts(); - setHosts(hostsData); const uniqueFolders = [ ...new Set( @@ -152,9 +158,8 @@ export function HostManagerEditor({ setFolders(uniqueFolders); setSshConfigurations(uniqueConfigurations); - } catch (error) { - } finally { - setLoading(false); + } catch { + // Failed to reload hosts after credential change } }; @@ -208,6 +213,32 @@ export function HostManagerEditor({ .default([]), enableFileManager: z.boolean().default(true), defaultPath: z.string().optional(), + statsConfig: z + .object({ + enabledWidgets: z + .array( + z.enum([ + "cpu", + "memory", + "disk", + "network", + "uptime", + "processes", + "system", + ]), + ) + .default(["cpu", "memory", "disk", "network", "uptime", "system"]), + }) + .default({ + enabledWidgets: [ + "cpu", + "memory", + "disk", + "network", + "uptime", + "system", + ], + }), }) .superRefine((data, ctx) => { if (data.authType === "password") { @@ -270,7 +301,7 @@ export function HostManagerEditor({ type FormData = z.infer; const form = useForm({ - resolver: zodResolver(formSchema) as any, + resolver: zodResolver(formSchema), defaultValues: { name: "", ip: "", @@ -290,6 +321,7 @@ export function HostManagerEditor({ enableFileManager: true, defaultPath: "/", tunnelConnections: [], + statsConfig: DEFAULT_STATS_CONFIG, }, }); @@ -346,6 +378,7 @@ export function HostManagerEditor({ enableFileManager: Boolean(cleanedHost.enableFileManager), defaultPath: cleanedHost.defaultPath || "/", tunnelConnections: cleanedHost.tunnelConnections || [], + statsConfig: cleanedHost.statsConfig || DEFAULT_STATS_CONFIG, }; if (defaultAuthType === "password") { @@ -353,7 +386,17 @@ export function HostManagerEditor({ } else if (defaultAuthType === "key") { formData.key = editingHost.id ? "existing_key" : editingHost.key; formData.keyPassword = cleanedHost.keyPassword || ""; - formData.keyType = (cleanedHost.keyType as any) || "auto"; + formData.keyType = + (cleanedHost.keyType as + | "auto" + | "ssh-rsa" + | "ssh-ed25519" + | "ecdsa-sha2-nistp256" + | "ecdsa-sha2-nistp384" + | "ecdsa-sha2-nistp521" + | "ssh-dss" + | "ssh-rsa-sha2-256" + | "ssh-rsa-sha2-512") || "auto"; } else if (defaultAuthType === "credential") { formData.credentialId = cleanedHost.credentialId || "existing_credential"; @@ -381,6 +424,7 @@ export function HostManagerEditor({ enableFileManager: true, defaultPath: "/", tunnelConnections: [], + statsConfig: DEFAULT_STATS_CONFIG, }; form.reset(defaultFormData); @@ -405,7 +449,7 @@ export function HostManagerEditor({ data.name = `${data.username}@${data.ip}`; } - const submitData: any = { + const submitData: Record = { name: data.name, ip: data.ip, port: data.port, @@ -419,6 +463,7 @@ export function HostManagerEditor({ enableFileManager: Boolean(data.enableFileManager), defaultPath: data.defaultPath || "/", tunnelConnections: data.tunnelConnections || [], + statsConfig: data.statsConfig || DEFAULT_STATS_CONFIG, }; submitData.credentialId = null; @@ -497,7 +542,7 @@ export function HostManagerEditor({ window.dispatchEvent(new CustomEvent("ssh-hosts:changed")); form.reset(); - } catch (error) { + } catch { toast.error(t("hosts.failedToSaveHost")); } finally { isSubmittingRef.current = false; @@ -667,6 +712,9 @@ export function HostManagerEditor({ {t("hosts.fileManager")} + + {t("hosts.statistics")} + @@ -1531,6 +1579,65 @@ export function HostManagerEditor({ )} + + ( + + {t("hosts.enabledWidgets")} + + {t("hosts.enabledWidgetsDesc")} + +
+ {( + [ + "cpu", + "memory", + "disk", + "network", + "uptime", + "processes", + "system", + ] as const + ).map((widget) => ( +
+ { + const currentWidgets = field.value || []; + if (checked) { + field.onChange([...currentWidgets, widget]); + } else { + field.onChange( + currentWidgets.filter((w) => w !== widget), + ); + } + }} + /> + +
+ ))} +
+
+ )} + /> +