From 7ddcb42f7f973c6fc09c1dcea5fd630c58de6d58 Mon Sep 17 00:00:00 2001 From: Karmaa <88517757+LukeGus@users.noreply.github.com> Date: Tue, 7 Oct 2025 20:06:01 -0500 Subject: [PATCH] Feature engineering improvements (#376) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: add engineering improvements - Configure Prettier with unified code style rules - Add husky + lint-staged for automated pre-commit checks - Add commitlint to enforce conventional commit messages - Add PR check workflow for CI automation - Auto-format all files with Prettier - Fix TypeScript any types in field-crypto.ts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * chore: enhance development environment - Add .editorconfig for unified editor settings - Add .nvmrc to specify Node.js version (20) - Add useful npm scripts: format, format:check, lint, lint:fix, type-check * chore: add IDE and Git configuration - Add VS Code workspace settings for consistent development experience - Add VS Code extension recommendations (ESLint, Prettier, EditorConfig) - Add .gitattributes to enforce LF line endings * refactor: clean up unused variables and empty blocks - database.ts: Remove unused variables (authManager, format, HTTPS_PORT, etc.) - database.ts: Fix empty catch blocks with descriptive comments - database.ts: Add eslint-disable for required middleware parameter - db/index.ts: Remove unused variables and fix empty catch blocks - Temporarily remove ESLint from pre-commit to allow incremental fixes Reduced total errors from 947 to 913 (34 fixes) * refactor: clean up unused variables and empty blocks in routes Routes updated: - credentials.ts: Remove 12 unused variables/imports - alerts.ts: Remove 1 unused variable - users.ts: Remove 9 unused variables/imports Changes: - Remove unused imports (NextFunction, jwt, UserCrypto, detectKeyType) - Fix empty catch blocks with descriptive comments - Prefix reserved parameters with underscore - Clean up unused error variables in catch blocks Reduced errors from 913 to 886 (27 fixes) * refactor: clean up unused variables in routes/ssh.ts - Remove unused imports (NextFunction, jwt) - Remove 6 unused variables (result, updateResult, name x3) - All 8 no-unused-vars errors fixed * refactor: clean up unused variables and empty blocks in file-manager.ts - Remove 22 unused variables (linkCount, hostId, userId, content, escapedTempFile, index, code) - Fix 1 empty catch block - Simplify multiple route handlers by removing unused destructured parameters Reduced errors from 878 to 855 (23 fixes) * refactor: clean up unused variables and empty blocks in utils database-migration.ts: - Remove 3 unused variables (encryptedSize, totalOriginalRows, totalMemoryRows) lazy-field-encryption.ts: - Fix 6 empty catch blocks with descriptive comments - Keep error variables where they are used in logging tunnel.ts: - Fix multiple empty catch blocks - Remove empty else blocks - Partially fixed (10/21 issues resolved) Reduced errors from 855 to 833 (22 fixes) * fix: restore error variable in catch block for logging Fix TypeScript error where error variable was removed from catch block but still used in logging statements. The error variable is needed for proper error logging and re-throwing. * fix: clean up tunnel.ts empty blocks and unused variables 移除了 tunnel.ts 中的空块和未使用的变量: - 移除 2 个空 else 块 - 修复 2 个空 if 块并添加注释 - 修复空错误处理器并添加注释 - 将未使用的 err 参数重命名为 _err 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: clean up empty blocks and unused variables in backend utils 修复了后端工具文件中的空块和未使用的变量: - auth-manager.ts: 移除空 else 块 - system-crypto.ts: 修复空 catch 块并添加注释 - starter.ts: 修复空 catch 块并添加注释 - server-stats.ts: 将未使用的 reject 参数重命名为 _reject - credentials.ts: 将 connectionTimeout 从 let 改为 const 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: clean up empty catch blocks in frontend components 修复了前端组件中的空 catch 块: - Tunnel.tsx: 修复空 catch 块并添加注释 - ServerConfig.tsx: 修复空 catch 块并添加注释 - TerminalKeyboard.tsx: 修复空 catch 块并添加注释 - system-crypto.ts: 修复遗漏的空 catch 块 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: clean up empty catch blocks in backend utilities 修复了后端工具文件中的 10 个空 catch 块: - system-crypto.ts: 修复 1 个空 catch 块 - server-stats.ts: 修复 4 个空 catch 块 - auto-ssl-setup.ts: 修复 1 个空 catch 块 - ssh-key-utils.ts: 修复 4 个空 catch 块 所有空块都添加了描述性注释说明为何忽略错误。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: clean up empty catch blocks in UI hooks and components 修复了 5 个 UI 组件和 hooks 中的空 catch 块: - useDragToSystemDesktop.ts: 修复 2 个空 catch 块 - HomepageAuth.tsx: 修复 1 个空 catch 块 - HostManagerEditor.tsx: 修复 2 个空 catch 块 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: clean up empty blocks in file manager and credential editor 修复了 5 个空块: - FileManagerGrid.tsx: 移除 1 个空 else 块和 1 个空 if 块 - CredentialEditor.tsx: 修复 1 个空 catch 块,移除 2 个空 if/else 块 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: clean up all empty catch blocks in Terminal components 修复了 Terminal 组件中的所有 8 个空 catch 块: - Desktop/Apps/Terminal/Terminal.tsx: 修复 5 个空 catch 块 - Mobile/Apps/Terminal/Terminal.tsx: 修复 3 个空 catch 块 所有空块都添加了描述性注释。这是空块修复的最后一批。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * refactor: remove useless try/catch wrappers 移除了 3 个无用的 try/catch 包装器: - users.ts: 移除只重新抛出错误的外层 try/catch - FileManager.tsx: 移除只重新抛出错误的内层 try/catch - DiffViewer.tsx: 移除只重新抛出错误的内层 try/catch 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * refactor: remove unused imports and mark unused parameters 移除了未使用的导入和标记未使用的参数: - auto-ssl-setup.ts: 移除未使用的 crypto 导入 - user-crypto.ts: 移除未使用的 users 导入 - user-data-import.ts: 移除未使用的 nanoid 导入 - simple-db-ops.ts: 标记未使用的 userId 和 tableName 参数 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude * fix: remove unnecessary escape characters in regex patterns 移除了正则表达式中不必要的转义字符: - users.ts: 修复 5 个 \/ 不必要的转义 - TabContext.tsx: 修复 1 个 \/ 不必要的转义 在字符串形式的正则表达式中,/ 不需要转义。 --------- Co-authored-by: ZacharyZcR Co-authored-by: Claude --- .commitlintrc.json | 21 + .editorconfig | 20 + .gitattributes | 36 + .github/workflows/pr-check.yml | 34 + .husky/commit-msg | 1 + .husky/pre-commit | 1 + .nvmrc | 2 +- .prettierignore | 20 + .prettierrc | 10 +- .vscode/extensions.json | 7 + package-lock.json | 1483 ++++++++++++++++- package.json | 20 +- src/backend/database/database.ts | 48 +- src/backend/database/db/index.ts | 23 +- src/backend/database/routes/alerts.ts | 2 +- src/backend/database/routes/credentials.ts | 40 +- src/backend/database/routes/ssh.ts | 15 +- src/backend/database/routes/users.ts | 189 +-- src/backend/ssh/file-manager.ts | 45 +- src/backend/ssh/server-stats.ts | 18 +- src/backend/ssh/tunnel.ts | 41 +- src/backend/starter.ts | 4 +- src/backend/utils/auth-manager.ts | 1 - src/backend/utils/auto-ssl-setup.ts | 5 +- src/backend/utils/database-migration.ts | 7 - src/backend/utils/field-crypto.ts | 11 +- src/backend/utils/lazy-field-encryption.ts | 16 +- src/backend/utils/simple-db-ops.ts | 4 +- src/backend/utils/ssh-key-utils.ts | 16 +- src/backend/utils/system-crypto.ts | 12 +- src/backend/utils/user-crypto.ts | 2 +- src/backend/utils/user-data-import.ts | 1 - .../Apps/Credentials/CredentialEditor.tsx | 7 +- .../Desktop/Apps/File Manager/FileManager.tsx | 36 +- .../Apps/File Manager/FileManagerGrid.tsx | 3 - .../File Manager/components/DiffViewer.tsx | 28 +- .../Apps/Host Manager/HostManagerEditor.tsx | 6 +- src/ui/Desktop/Apps/Terminal/Terminal.tsx | 20 +- src/ui/Desktop/Apps/Tunnel/Tunnel.tsx | 3 +- src/ui/Desktop/Electron Only/ServerConfig.tsx | 4 +- src/ui/Desktop/Homepage/HomepageAuth.tsx | 4 +- src/ui/Desktop/Navigation/Tabs/TabContext.tsx | 2 +- src/ui/Mobile/Apps/Terminal/Terminal.tsx | 12 +- .../Mobile/Apps/Terminal/TerminalKeyboard.tsx | 4 +- src/ui/hooks/useDragToSystemDesktop.ts | 8 +- src/ui/main-axios.ts | 2 +- 46 files changed, 1973 insertions(+), 321 deletions(-) create mode 100644 .commitlintrc.json create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/pr-check.yml create mode 100644 .husky/commit-msg create mode 100644 .husky/pre-commit create mode 100644 .vscode/extensions.json 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/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 00000000..252adbcb --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,34 @@ +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" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - 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/.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/package-lock.json b/package-lock.json index bd087a93..9054dd7d 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", @@ -90,6 +90,8 @@ "zod": "^4.0.5" }, "devDependencies": { + "@commitlint/cli": "^20.1.0", + "@commitlint/config-conventional": "^20.0.0", "@eslint/js": "^9.34.0", "@types/better-sqlite3": "^7.6.13", "@types/cors": "^2.8.19", @@ -108,12 +110,39 @@ "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", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/runtime": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", @@ -519,6 +548,438 @@ "w3c-keyname": "^2.2.4" } }, + "node_modules/@commitlint/cli": { + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.1.0.tgz", + "integrity": "sha512-pW5ujjrOovhq5RcYv5xCpb4GkZxkO2+GtOdBW2/qrr0Ll9tl3PX0aBBobGQl3mdZUbOBgwAexEQLeH6uxL0VYg==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.0.0.tgz", + "integrity": "sha512-q7JroPIkDBtyOkVe9Bca0p7kAUYxZMxkrBArCfuD3yN4KjRAenP9PmYwnn7rsw8Q+hHq1QB2BRmBh0/Z19ZoJw==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-20.0.0.tgz", + "integrity": "sha512-BeyLMaRIJDdroJuYM2EGhDMGwVBMZna9UiIqV9hxj+J551Ctc6yoGuGSmghOy/qPhBSuhA6oMtbEiTmxECafsg==", + "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", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "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", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/@commitlint/ensure": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.0.0.tgz", + "integrity": "sha512-WBV47Fffvabe68n+13HJNFBqiMH5U1Ryls4W3ieGwPC0C7kJqp3OVQQzG2GXqOALmzrgAB+7GXmyy8N9ct8/Fg==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-20.0.0.tgz", + "integrity": "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/format": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-20.0.0.tgz", + "integrity": "sha512-zrZQXUcSDmQ4eGGrd+gFESiX0Rw+WFJk7nW4VFOmxub4mAATNKBQ4vNw5FgMCVehLUKG2OT2LjOqD0Hk8HvcRg==", + "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", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-20.0.0.tgz", + "integrity": "sha512-ayPLicsqqGAphYIQwh9LdAYOVAQ9Oe5QCgTNTj+BfxZb9b/JW222V5taPoIBzYnAP0z9EfUtljgBk+0BN4T4Cw==", + "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", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/lint": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.0.0.tgz", + "integrity": "sha512-kWrX8SfWk4+4nCexfLaQT3f3EcNjJwJBsSZ5rMBw6JCd6OzXufFHgel2Curos4LKIxwec9WSvs2YUD87rXlxNQ==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.1.0.tgz", + "integrity": "sha512-qo9ER0XiAimATQR5QhvvzePfeDfApi/AFlC1G+YN+ZAY8/Ua6IRrDrxRvQAr+YXUKAxUsTDSp9KXeXLBPsNRWg==", + "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", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-20.0.0.tgz", + "integrity": "sha512-gLX4YmKnZqSwkmSB9OckQUrI5VyXEYiv3J5JKZRxIp8jOQsWjZgHSG/OgEfMQBK9ibdclEdAyIPYggwXoFGXjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/parse": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-20.0.0.tgz", + "integrity": "sha512-j/PHCDX2bGM5xGcWObOvpOc54cXjn9g6xScXzAeOLwTsScaL4Y+qd0pFC6HBwTtrH92NvJQc+2Lx9HFkVi48cg==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-20.0.0.tgz", + "integrity": "sha512-Ti7Y7aEgxsM1nkwA4ZIJczkTFRX/+USMjNrL9NXwWQHqNqrBX2iMi+zfuzZXqfZ327WXBjdkRaytJ+z5vNqTOA==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.1.0.tgz", + "integrity": "sha512-cxKXQrqHjZT3o+XPdqDCwOWVFQiae++uwd9dUBC7f2MdV58ons3uUvASdW7m55eat5sRiQ6xUHyMWMRm6atZWw==", + "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", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@commitlint/rules": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.0.0.tgz", + "integrity": "sha512-gvg2k10I/RfvHn5I5sxvVZKM1fl72Sqrv2YY/BnM7lMHcYqO0E2jnRWoYguvBfEcZ39t+rbATlciggVe77E4zA==", + "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", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-20.0.0.tgz", + "integrity": "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v18" + } + }, + "node_modules/@commitlint/top-level": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-20.0.0.tgz", + "integrity": "sha512-drXaPSP2EcopukrUXvUXmsQMu3Ey/FuJDc/5oiW4heoCfoE5BdLQyuc7veGeE3aoQaTVqZnh4D5WTWe2vefYKg==", + "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", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz", + "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==", + "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", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "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", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "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", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "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", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "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", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-20.0.0.tgz", + "integrity": "sha512-bVUNBqG6aznYcYjTjnc3+Cat/iBgbgpflxbIBTnsHTX0YVpnmINPEkSRWymT2Q8aSH3Y7aKnEbunilkYe8TybA==", + "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", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "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", @@ -864,6 +1325,8 @@ "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", "dev": true, "license": "BSD-2-Clause", + "optional": true, + "peer": true, "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", @@ -886,6 +1349,8 @@ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -904,6 +1369,8 @@ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -932,6 +1399,8 @@ "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -945,6 +1414,9 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/@electron/osx-sign/node_modules/universalify": { "version": "2.0.1", @@ -952,6 +1424,8 @@ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">= 10.0.0" } @@ -4868,6 +5342,16 @@ "@types/node": "*" } }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.1.tgz", + "integrity": "sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/cookie-parser": { "version": "1.4.9", "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.9.tgz", @@ -5847,6 +6331,22 @@ "ajv": "^6.9.1" } }, + "node_modules/ansi-escapes": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz", + "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==", + "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", @@ -6069,6 +6569,13 @@ "node": ">=10" } }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, "node_modules/asn1": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", @@ -7027,6 +7534,13 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "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", @@ -7059,6 +7573,17 @@ "node": ">= 6" } }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "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", @@ -7235,6 +7760,51 @@ "node": ">= 0.6" } }, + "node_modules/conventional-changelog-angular": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz", + "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==", + "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", @@ -7282,6 +7852,51 @@ "node": ">= 0.10" } }, + "node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "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", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.1.0.tgz", + "integrity": "sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jiti": "^2.4.1" + }, + "engines": { + "node": ">=v18" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=9", + "typescript": ">=5" + } + }, "node_modules/cpu-features": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", @@ -7349,6 +7964,19 @@ "integrity": "sha512-cjrsQufETwxjvwZbYbKBCJNvmQ2++G9AvT45zDi7NXL9k2PdVcs2h0jQz96J6G4TMKRCcEsoJ+QTgQD00Igtjw==", "license": "MIT" }, + "node_modules/dargs": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz", + "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==", + "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", @@ -7721,6 +8349,19 @@ "node": ">=8" } }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "17.2.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", @@ -8244,6 +8885,19 @@ "node": ">=6" } }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "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", @@ -8251,6 +8905,16 @@ "dev": true, "license": "MIT" }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "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", @@ -8609,6 +9273,13 @@ "node": ">= 0.6" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true, + "license": "MIT" + }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -8692,6 +9363,14 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "license": "MIT", + "peer": true, + "dependencies": { + "@electron/asar": "^3.2.1", + "debug": "^4.1.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.21", + "temp": "^0.9.0" + }, "engines": { "node": ">=6.6.0" } @@ -8701,6 +9380,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -8718,6 +9398,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", + "peer": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -8738,7 +9419,9 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "dev": true, + "license": "MIT", + "peer": true }, "node_modules/express/node_modules/qs": { "version": "6.14.0", @@ -8913,6 +9596,23 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "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", @@ -9310,6 +10010,19 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "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", @@ -9372,6 +10085,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/git-raw-commits": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", + "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==", + "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", @@ -9459,6 +10190,32 @@ "node": ">=10" } }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "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", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "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", @@ -9932,6 +10689,22 @@ "ms": "^2.0.0" } }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "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", @@ -10055,6 +10828,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "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", @@ -10170,6 +10954,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "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", @@ -10262,6 +11053,16 @@ "node": ">=0.12.0" } }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "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", @@ -10280,6 +11081,19 @@ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "license": "MIT" }, + "node_modules/is-text-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz", + "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==", + "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", @@ -10421,6 +11235,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "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", @@ -10449,8 +11270,11 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", - "bin": { - "json5": "lib/cli.js" + "dependencies": { + "@babel/runtime": "^7.27.6" + }, + "peerDependencies": { + "typescript": "^5" }, "engines": { "node": ">=6" @@ -10466,6 +11290,33 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "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", @@ -10807,6 +11658,218 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.2.3.tgz", + "integrity": "sha512-1OnJEESB9zZqsp61XHH2fvpS1es3hRCxMplF/AJUDa8Ho8VrscYDIuxGrj3m8KPXbcWZ8fT9XTMUhEQmOVKpKw==", + "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", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.1.tgz", + "integrity": "sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/listr2": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.4.tgz", + "integrity": "sha512-1wd/kpAdKRLwv7/3OKC8zZ5U8e/fajCfWMxacUvB79S5nLrYGPtUI/8chMQhn3LQjsRVErTb9i1ECAwW0ZIHnQ==", + "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", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "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", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "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", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.1.0.tgz", + "integrity": "sha512-7JDGG+4Zp0CsknDCedl0DYdaeOhc46QNpXi3NLQblkZpXXgA6LncLDUUyvrjSvZeF3VRQa+KiMGomazQrC1V8g==", + "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", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "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", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "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", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.1.0.tgz", + "integrity": "sha512-Kxl3KJGb/gxkaUMOjRsQ8IrXiGW75O4E3RPjFIINOVH8AMl2SQ/yWdTzWwF3FevIX9LcMAjJW+GRwAlAbTSXdg==", + "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", + "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": { + "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", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "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", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "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", @@ -10847,6 +11910,13 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "license": "MIT" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "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", @@ -10883,6 +11953,13 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "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", @@ -10890,12 +11967,47 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "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", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "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", @@ -10913,6 +12025,206 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "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", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "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", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "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", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "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", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "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", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "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", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "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", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "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", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "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", + "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": { + "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", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "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", @@ -11462,6 +12774,19 @@ "node": ">= 0.6" } }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "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", @@ -12145,6 +13470,19 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "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", @@ -12355,6 +13693,19 @@ "license": "MIT", "optional": true }, + "node_modules/nano-spawn": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.3.tgz", + "integrity": "sha512-jtpsQDetTnvS2Ts1fiRdci5rx0VYws5jGyC+4IYOTnIQ/wwdf6JdomlHBwqC3bJYOvaKu0C2GSZ1A60anrYpaA==", + "dev": true, + "license": "MIT", + "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", @@ -12762,6 +14113,25 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "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", @@ -12903,6 +14273,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "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", @@ -13974,6 +15357,16 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -14063,6 +15456,13 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -14717,6 +16117,16 @@ "node": ">= 0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "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", @@ -14809,6 +16219,16 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "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", @@ -15197,6 +16617,26 @@ "rimraf": "bin.js" } }, + "node_modules/text-extensions": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz", + "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "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", @@ -15229,6 +16669,13 @@ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "license": "MIT" }, + "node_modules/tinyexec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz", + "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -15536,6 +16983,19 @@ "integrity": "sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ==", "license": "MIT" }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "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", @@ -16119,6 +17579,19 @@ "dev": true, "license": "ISC" }, + "node_modules/yaml": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", + "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", + "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", diff --git a/package.json b/package.json index 3151adaa..67fdd920 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,11 @@ "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", @@ -20,7 +25,8 @@ "build:linux-appimage": "npm run build && electron-builder --linux AppImage", "build:linux-targz": "npm run build && electron-builder --linux tar.gz", "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", @@ -105,6 +111,8 @@ "zod": "^4.0.5" }, "devDependencies": { + "@commitlint/cli": "^20.1.0", + "@commitlint/config-conventional": "^20.0.0", "@eslint/js": "^9.34.0", "@types/better-sqlite3": "^7.6.13", "@types/cors": "^2.8.19", @@ -123,9 +131,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/src/backend/database/database.ts b/src/backend/database/database.ts index 2f9899a2..36f6f070 100644 --- a/src/backend/database/database.ts +++ b/src/backend/database/database.ts @@ -259,7 +259,7 @@ app.get("/version", authenticateJWT, async (req, res) => { localVersion = foundVersion; break; } - } catch (error) { + } catch { continue; } } @@ -374,7 +374,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 }, @@ -419,8 +418,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", }); @@ -442,8 +439,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", }); @@ -970,7 +965,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) { @@ -1061,7 +1056,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info("ssh_data table not found in import file, skipping"); } @@ -1122,7 +1117,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info( "ssh_credentials table not found in import file, skipping", ); @@ -1193,7 +1188,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info(`${table} table not found in import file, skipping`); } } @@ -1231,7 +1226,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info( "dismissed_alerts table not found in import file, skipping", ); @@ -1272,7 +1267,7 @@ app.post( ); } } - } catch (tableError) { + } catch { apiLogger.info("settings table not found in import file, skipping"); } } else { @@ -1290,7 +1285,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, @@ -1316,7 +1311,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, @@ -1339,11 +1334,7 @@ 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 { scope = "user_data", includeCredentials = true } = req.body; const exportData = await UserDataExport.exportUserData(userId, { format: "encrypted", @@ -1420,7 +1411,8 @@ 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", @@ -1433,7 +1425,6 @@ app.use( ); const HTTP_PORT = 30001; -const HTTPS_PORT = process.env.SSL_PORT || 8443; async function initializeSecurity() { try { @@ -1446,13 +1437,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", @@ -1484,13 +1468,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 d45fc333..acc0e375 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)) { @@ -288,7 +289,7 @@ const addColumnIfNotExists = ( FROM ${table} LIMIT 1`, ) .get(); - } catch (e) { + } catch { try { sqlite.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition};`); @@ -487,21 +488,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/routes/alerts.ts b/src/backend/database/routes/alerts.ts index 4f836894..f1f113ff 100644 --- a/src/backend/database/routes/alerts.ts +++ b/src/backend/database/routes/alerts.ts @@ -170,7 +170,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, }); diff --git a/src/backend/database/routes/credentials.ts b/src/backend/database/routes/credentials.ts index c856322f..b85bb5ec 100644 --- a/src/backend/database/routes/credentials.ts +++ b/src/backend/database/routes/credentials.ts @@ -2,15 +2,13 @@ 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"; @@ -970,7 +968,7 @@ router.post( try { let privateKeyObj; - let parseAttempts = []; + const parseAttempts = []; try { privateKeyObj = crypto.createPrivateKey({ @@ -1093,7 +1091,9 @@ router.post( finalPublicKey = `${keyType} ${base64Data}`; formatType = "ssh"; } - } catch (sshError) {} + } catch { + // Ignore validation errors + } const response = { success: true, @@ -1119,13 +1119,13 @@ router.post( async function deploySSHKeyToHost( hostConfig: any, publicKey: string, - credentialData: any, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _credentialData: any, ): 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 +1158,9 @@ async function deploySSHKeyToHost( } }); - stream.on("data", (data) => {}); + stream.on("data", () => { + // Ignore output + }); }, ); }); @@ -1175,7 +1177,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 +1206,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 +1233,9 @@ async function deploySSHKeyToHost( if (parsed.data) { actualPublicKey = parsed.data; } - } catch (e) {} + } catch { + // Ignore parse errors + } const escapedKey = actualPublicKey .replace(/\\/g, "\\\\") @@ -1269,7 +1275,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 +1303,7 @@ async function deploySSHKeyToHost( output += data.toString(); }); - stream.on("close", (code) => { + stream.on("close", () => { clearTimeout(verifyTimeout); const verified = output.trim() === "0"; resolveVerify(verified); @@ -1521,7 +1529,7 @@ router.post( const hostData = targetHost[0]; - let hostConfig = { + const hostConfig = { ip: hostData.ip, port: hostData.port, username: hostData.username, @@ -1571,7 +1579,7 @@ router.post( error: "Host credential not found", }); } - } catch (error) { + } catch { return res.status(500).json({ success: false, error: "Failed to resolve host credentials", diff --git a/src/backend/database/routes/ssh.ts b/src/backend/database/routes/ssh.ts index cf75f4f0..5c4ce328 100644 --- a/src/backend/database/routes/ssh.ts +++ b/src/backend/database/routes/ssh.ts @@ -9,8 +9,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"; @@ -816,7 +815,7 @@ router.delete( ), ); - const result = await db + await db .delete(sshData) .where(and(eq(sshData.id, numericHostId), eq(sshData.userId, userId))); @@ -943,7 +942,7 @@ router.delete( authenticateJWT, async (req: Request, res: Response) => { const userId = (req as any).userId; - const { hostId, path, name } = req.body; + const { hostId, path } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { sshLogger.warn("Invalid data for recent file deletion"); @@ -1063,7 +1062,7 @@ router.delete( authenticateJWT, async (req: Request, res: Response) => { const userId = (req as any).userId; - const { hostId, path, name } = req.body; + const { hostId, path } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { sshLogger.warn("Invalid data for pinned file deletion"); @@ -1183,7 +1182,7 @@ router.delete( authenticateJWT, async (req: Request, res: Response) => { const userId = (req as any).userId; - const { hostId, path, name } = req.body; + const { hostId, path } = req.body; if (!isNonEmptyString(userId) || !hostId || !path) { sshLogger.warn("Invalid data for shortcut deletion"); @@ -1573,7 +1572,7 @@ router.post( } } - const updateResult = await db + await db .update(sshData) .set({ autostartPassword: decryptedConfig.password || null, @@ -1630,7 +1629,7 @@ router.delete( } try { - const result = await db + await db .update(sshData) .set({ autostartPassword: null, diff --git a/src/backend/database/routes/users.ts b/src/backend/database/routes/users.ts index cb572ce9..92d9451a 100644 --- a/src/backend/database/routes/users.ts +++ b/src/backend/database/routes/users.ts @@ -18,7 +18,6 @@ import QRCode from "qrcode"; import type { Request, Response } from "express"; import { authLogger } from "../../utils/logger.js"; import { AuthManager } from "../../utils/auth-manager.js"; -import { UserCrypto } from "../../utils/user-crypto.js"; import { DataCrypto } from "../../utils/data-crypto.js"; import { LazyFieldEncryption } from "../../utils/lazy-field-encryption.js"; @@ -29,94 +28,89 @@ async function verifyOIDCToken( issuerUrl: string, clientId: string, ): 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); - } - } - } catch (discoveryError) { - authLogger.error(`OIDC discovery failed: ${discoveryError}`); - } - - let jwks: any = null; - let jwksUrl: string | null = null; - - for (const url of jwksUrls) { - try { - const response = await fetch(url); - if (response.ok) { - const jwksData = (await response.json()) as any; - if (jwksData && jwksData.keys && Array.isArray(jwksData.keys)) { - jwks = jwksData; - jwksUrl = url; - break; - } else { - authLogger.error( - `Invalid JWKS structure from ${url}: ${JSON.stringify(jwksData)}`, - ); - } - } else { - } - } catch (error) { - continue; + 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); } } - - 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; + } catch (discoveryError) { + authLogger.error(`OIDC discovery failed: ${discoveryError}`); } + + let jwks: any = null; + + for (const url of jwksUrls) { + try { + const response = await fetch(url); + if (response.ok) { + const jwksData = (await response.json()) as any; + if (jwksData && jwksData.keys && Array.isArray(jwksData.keys)) { + jwks = jwksData; + break; + } else { + authLogger.error( + `Invalid JWKS structure from ${url}: ${JSON.stringify(jwksData)}`, + ); + } + } else { + // Non-200 response + } + } 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; } const router = express.Router(); @@ -125,15 +119,8 @@ function isNonEmptyString(val: any): 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 @@ -451,7 +438,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, @@ -504,7 +491,7 @@ router.get("/oidc/authorize", async (req, res) => { let origin = req.get("Origin") || - req.get("Referer")?.replace(/\/[^\/]*$/, "") || + req.get("Referer")?.replace(/\/[^/]*$/, "") || "http://localhost:5173"; if (origin.includes("localhost")) { @@ -606,15 +593,12 @@ router.get("/oidc/callback", async (req, res) => { const tokenData = (await tokenResponse.json()) as any; let userInfo: any = null; - let userInfoUrls: string[] = []; + 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`; @@ -651,7 +635,8 @@ router.get("/oidc/callback", async (req, res) => { config.issuer_url, config.client_id, ); - } catch (error) { + } catch { + // Fallback to manual decoding try { const parts = tokenData.id_token.split("."); if (parts.length === 3) { @@ -911,7 +896,7 @@ router.post("/login", async (req, res) => { if (kekSalt.length === 0) { await authManager.registerUser(userRecord.id, password); } - } catch (setupError) { + } catch { // Continue if setup fails - authenticateUser will handle it } @@ -1615,7 +1600,7 @@ router.post("/totp/verify-login", async (req, res) => { backupCodes = userRecord.totp_backup_codes ? JSON.parse(userRecord.totp_backup_codes) : []; - } catch (parseError) { + } catch { backupCodes = []; } diff --git a/src/backend/ssh/file-manager.ts b/src/backend/ssh/file-manager.ts index 1de80050..4cc4642d 100644 --- a/src/backend/ssh/file-manager.ts +++ b/src/backend/ssh/file-manager.ts @@ -110,7 +110,9 @@ function cleanupSession(sessionId: string) { if (session) { try { session.client.end(); - } catch {} + } catch { + // Ignore connection close errors + } clearTimeout(session.timeout); delete sshSessions[sessionId]; } @@ -598,13 +600,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]}`; @@ -837,7 +838,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) { @@ -1024,14 +1025,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) { @@ -1165,8 +1159,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"`; @@ -1231,13 +1223,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}'`; }); @@ -1320,14 +1310,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) { @@ -1428,7 +1411,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) { @@ -1529,7 +1512,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) { @@ -1631,7 +1614,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) { @@ -1739,7 +1722,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) { @@ -2128,7 +2111,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) { @@ -2165,7 +2148,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 0ca9ead6..da0897ff 100644 --- a/src/backend/ssh/server-stats.ts +++ b/src/backend/ssh/server-stats.ts @@ -60,7 +60,7 @@ class SSHConnectionPool { return client; } - return new Promise((resolve, reject) => { + return new Promise((resolve, _reject) => { const checkAvailable = () => { const available = connections.find((conn) => !conn.inUse); if (available) { @@ -157,7 +157,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; @@ -177,7 +179,9 @@ class SSHConnectionPool { for (const conn of connections) { try { conn.client.end(); - } catch {} + } catch { + // Ignore errors when closing connections during cleanup + } } } this.connections.clear(); @@ -215,7 +219,9 @@ class RequestQueue { if (request) { try { await request(); - } catch (error) {} + } catch { + // Ignore errors from queued requests + } } } @@ -871,7 +877,9 @@ function tcpPing( settled = true; try { socket.destroy(); - } catch {} + } catch { + // Ignore errors when destroying socket + } resolve(result); }; diff --git a/src/backend/ssh/tunnel.ts b/src/backend/ssh/tunnel.ts index b49606e6..b652d857 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); } @@ -518,9 +522,7 @@ async function connectSSHTunnel( keyType: credential.key_type || credential.keyType, authMethod: credential.auth_type || credential.authType, }; - } else { } - } else { } } catch (error) { tunnelLogger.warn("Failed to resolve source credentials from database", { @@ -605,7 +607,6 @@ async function connectSSHTunnel( credentialId: tunnelConfig.endpointCredentialId, }); } - } else { } } catch (error) { tunnelLogger.warn( @@ -631,7 +632,9 @@ async function connectSSHTunnel( try { conn.end(); - } catch (e) {} + } catch { + // Ignore errors + } activeTunnels.delete(tunnelName); @@ -771,7 +774,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); } @@ -823,12 +828,12 @@ async function connectSSHTunnel( }); stream.stdout?.on("data", (data: Buffer) => { - const output = data.toString().trim(); - if (output) { - } + // 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(); @@ -1034,7 +1039,6 @@ async function killRemoteTunnelByMarker( authMethod: credential.auth_type || credential.authType, }; } - } else { } } catch (error) { tunnelLogger.warn("Failed to resolve source credentials for cleanup", { @@ -1122,7 +1126,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 +1154,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 +1187,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) => { diff --git a/src/backend/starter.ts b/src/backend/starter.ts index fb0cfc89..a7244082 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"; diff --git a/src/backend/utils/auth-manager.ts b/src/backend/utils/auth-manager.ts index 541d889f..e85bae28 100644 --- a/src/backend/utils/auth-manager.ts +++ b/src/backend/utils/auth-manager.ts @@ -108,7 +108,6 @@ class AuthManager { if (migrationResult.migrated) { await saveMemoryDatabaseToFile(); - } else { } } catch (error) { databaseLogger.error("Lazy encryption migration failed", error, { diff --git a/src/backend/utils/auto-ssl-setup.ts b/src/backend/utils/auto-ssl-setup.ts index e2d1034a..a8d022d4 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 { @@ -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/database-migration.ts b/src/backend/utils/database-migration.ts index ebf3192b..0fba053e 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", 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..98f7aa44 100644 --- a/src/backend/utils/lazy-field-encryption.ts +++ b/src/backend/utils/lazy-field-encryption.ts @@ -39,7 +39,7 @@ export class LazyFieldEncryption { return false; } return true; - } catch (jsonError) { + } catch { return true; } } @@ -74,7 +74,9 @@ export class LazyFieldEncryption { legacyFieldName, ); return decrypted; - } catch (legacyError) {} + } catch { + // Ignore legacy format errors + } } const sensitiveFields = [ @@ -145,7 +147,7 @@ export class LazyFieldEncryption { wasPlaintext: false, wasLegacyEncryption: false, }; - } catch (error) { + } catch { const legacyFieldName = this.LEGACY_FIELD_NAME_MAP[fieldName]; if (legacyFieldName) { try { @@ -166,7 +168,9 @@ export class LazyFieldEncryption { wasPlaintext: false, wasLegacyEncryption: true, }; - } catch (legacyError) {} + } catch { + // Ignore legacy format errors + } } return { encrypted: fieldValue, @@ -253,7 +257,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 +268,7 @@ export class LazyFieldEncryption { legacyFieldName, ); return true; - } catch (legacyError) { + } catch { return false; } } diff --git a/src/backend/utils/simple-db-ops.ts b/src/backend/utils/simple-db-ops.ts index c324e0a2..933a3a5e 100644 --- a/src/backend/utils/simple-db-ops.ts +++ b/src/backend/utils/simple-db-ops.ts @@ -127,7 +127,7 @@ class SimpleDBOps { table: SQLiteTable, tableName: TableName, where: any, - userId: string, + _userId: string, ): Promise { const result = await getDb().delete(table).where(where).returning(); @@ -146,7 +146,7 @@ class SimpleDBOps { static async selectEncrypted( query: any, - tableName: TableName, + _tableName: TableName, ): Promise { const results = await query; diff --git a/src/backend/utils/ssh-key-utils.ts b/src/backend/utils/ssh-key-utils.ts index b19f95c9..9a9f813d 100644 --- a/src/backend/utils/ssh-key-utils.ts +++ b/src/backend/utils/ssh-key-utils.ts @@ -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"; @@ -242,7 +246,9 @@ export function parseSSHKey( 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, 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 73a2e39f..e06a7467 100644 --- a/src/backend/utils/user-crypto.ts +++ b/src/backend/utils/user-crypto.ts @@ -1,6 +1,6 @@ import crypto from "crypto"; import { getDb } from "../database/db/index.js"; -import { settings, users } from "../database/db/schema.js"; +import { settings } from "../database/db/schema.js"; import { eq } from "drizzle-orm"; import { databaseLogger } from "./logger.js"; diff --git a/src/backend/utils/user-data-import.ts b/src/backend/utils/user-data-import.ts index 448d3c00..60f41dac 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; diff --git a/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx b/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx index 9303c0b8..84119637 100644 --- a/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx +++ b/src/ui/Desktop/Apps/Credentials/CredentialEditor.tsx @@ -79,7 +79,8 @@ export function CredentialEditor({ ].sort() as string[]; setFolders(uniqueFolders); - } catch (error) { + } catch { + // Failed to load credentials } finally { setLoading(false); } @@ -636,10 +637,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/File Manager/FileManager.tsx b/src/ui/Desktop/Apps/File Manager/FileManager.tsx index 779b2c33..0945fa88 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManager.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManager.tsx @@ -719,28 +719,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); diff --git a/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx b/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx index 039f75eb..0a636411 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManagerGrid.tsx @@ -327,7 +327,6 @@ export function FileManagerGrid({ dragState.files[0].type === "file" ) { onFileDiff?.(dragState.files[0], targetFile); - } else { } setDragState({ type: "none", files: [], counter: 0 }); @@ -458,8 +457,6 @@ export function FileManagerGrid({ type: "external", counter: prev.counter + 1, })); - if (e.dataTransfer.items && e.dataTransfer.items.length > 0) { - } } }, [dragState.type], diff --git a/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx b/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx index e9312924..be0bc85a 100644 --- a/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx +++ b/src/ui/Desktop/Apps/File Manager/components/DiffViewer.tsx @@ -62,22 +62,18 @@ export function DiffViewer({ }); } } 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; - } + 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, + }); } }; diff --git a/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx b/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx index 0fe881ef..b5eff4da 100644 --- a/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx +++ b/src/ui/Desktop/Apps/Host Manager/HostManagerEditor.tsx @@ -118,7 +118,8 @@ export function HostManagerEditor({ setFolders(uniqueFolders); setSshConfigurations(uniqueConfigurations); - } catch (error) { + } catch { + // Failed to load hosts data } finally { setLoading(false); } @@ -152,7 +153,8 @@ export function HostManagerEditor({ setFolders(uniqueFolders); setSshConfigurations(uniqueConfigurations); - } catch (error) { + } catch { + // Failed to reload hosts after credential change } finally { setLoading(false); } diff --git a/src/ui/Desktop/Apps/Terminal/Terminal.tsx b/src/ui/Desktop/Apps/Terminal/Terminal.tsx index 5d04e93c..dd6f72fd 100644 --- a/src/ui/Desktop/Apps/Terminal/Terminal.tsx +++ b/src/ui/Desktop/Apps/Terminal/Terminal.tsx @@ -102,7 +102,9 @@ export const Terminal = forwardRef(function SSHTerminal( if (terminal && typeof (terminal as any).refresh === "function") { (terminal as any).refresh(0, terminal.rows - 1); } - } catch (_) {} + } catch { + // Ignore terminal refresh errors + } } function handleTotpSubmit(code: string) { @@ -183,7 +185,9 @@ export const Terminal = forwardRef(function SSHTerminal( scheduleNotify(cols, rows); hardRefresh(); } - } catch (_) {} + } catch { + // Ignore resize notification errors + } }, refresh: () => hardRefresh(), }), @@ -505,7 +509,9 @@ export const Terminal = forwardRef(function SSHTerminal( await navigator.clipboard.writeText(text); return; } - } catch (_) {} + } catch { + // Clipboard API not available, fallback to textarea method + } const textarea = document.createElement("textarea"); textarea.value = text; textarea.style.position = "fixed"; @@ -525,7 +531,9 @@ export const Terminal = forwardRef(function SSHTerminal( if (navigator.clipboard && navigator.clipboard.readText) { return await navigator.clipboard.readText(); } - } catch (_) {} + } catch { + // Clipboard read not available or not permitted + } return ""; } @@ -585,7 +593,9 @@ export const Terminal = forwardRef(function SSHTerminal( const pasteText = await readTextFromClipboard(); if (pasteText) terminal.paste(pasteText); } - } catch (_) {} + } catch { + // Ignore clipboard operation errors + } }; element?.addEventListener("contextmenu", handleContextMenu); diff --git a/src/ui/Desktop/Apps/Tunnel/Tunnel.tsx b/src/ui/Desktop/Apps/Tunnel/Tunnel.tsx index 45c6f7cf..f658c3e1 100644 --- a/src/ui/Desktop/Apps/Tunnel/Tunnel.tsx +++ b/src/ui/Desktop/Apps/Tunnel/Tunnel.tsx @@ -191,7 +191,8 @@ export function Tunnel({ filterHostKey }: SSHTunnelProps): React.ReactElement { } await fetchTunnelStatuses(); - } catch (err) { + } catch { + // Ignore tunnel action errors } finally { setTunnelActions((prev) => ({ ...prev, [tunnelName]: false })); } diff --git a/src/ui/Desktop/Electron Only/ServerConfig.tsx b/src/ui/Desktop/Electron Only/ServerConfig.tsx index 3096ccf1..2343b519 100644 --- a/src/ui/Desktop/Electron Only/ServerConfig.tsx +++ b/src/ui/Desktop/Electron Only/ServerConfig.tsx @@ -43,7 +43,9 @@ export function ServerConfig({ setServerUrl(config.serverUrl); setConnectionStatus("success"); } - } catch (error) {} + } catch { + // Ignore config loading errors + } }; const handleTestConnection = async () => { diff --git a/src/ui/Desktop/Homepage/HomepageAuth.tsx b/src/ui/Desktop/Homepage/HomepageAuth.tsx index 70fd6ec4..21c533aa 100644 --- a/src/ui/Desktop/Homepage/HomepageAuth.tsx +++ b/src/ui/Desktop/Homepage/HomepageAuth.tsx @@ -105,7 +105,9 @@ export function HomepageAuth({ const clearJWTOnLoad = async () => { try { await logoutUser(); - } catch (error) {} + } catch { + // Ignore logout errors on initial load + } }; clearJWTOnLoad(); diff --git a/src/ui/Desktop/Navigation/Tabs/TabContext.tsx b/src/ui/Desktop/Navigation/Tabs/TabContext.tsx index 42b9b885..0f5d6d32 100644 --- a/src/ui/Desktop/Navigation/Tabs/TabContext.tsx +++ b/src/ui/Desktop/Navigation/Tabs/TabContext.tsx @@ -69,7 +69,7 @@ export function TabProvider({ children }: TabProviderProps) { } const m = t.title.match( new RegExp( - `^${root.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&")} \\((\\d+)\\)$`, + `^${root.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")} \\((\\d+)\\)$`, ), ); if (m) { diff --git a/src/ui/Mobile/Apps/Terminal/Terminal.tsx b/src/ui/Mobile/Apps/Terminal/Terminal.tsx index 63b09735..e27453e1 100644 --- a/src/ui/Mobile/Apps/Terminal/Terminal.tsx +++ b/src/ui/Mobile/Apps/Terminal/Terminal.tsx @@ -73,7 +73,9 @@ export const Terminal = forwardRef(function SSHTerminal( if (terminal && typeof (terminal as any).refresh === "function") { (terminal as any).refresh(0, terminal.rows - 1); } - } catch (_) {} + } catch { + // Ignore terminal refresh errors + } } function scheduleNotify(cols: number, rows: number) { @@ -122,7 +124,9 @@ export const Terminal = forwardRef(function SSHTerminal( scheduleNotify(cols, rows); hardRefresh(); } - } catch (_) {} + } catch { + // Ignore resize notification errors + } }, refresh: () => hardRefresh(), }), @@ -175,7 +179,9 @@ export const Terminal = forwardRef(function SSHTerminal( `\r\n[${msg.message || t("terminal.disconnected")}]`, ); } - } catch (error) {} + } catch { + // Ignore message parsing errors + } }); ws.addEventListener("close", (event) => { diff --git a/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx b/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx index 66667060..597d10dc 100644 --- a/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx +++ b/src/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx @@ -110,7 +110,9 @@ export function TerminalKeyboard({ if (navigator.vibrate) { navigator.vibrate(20); } - } catch (e) {} + } catch { + // Ignore vibration errors on unsupported devices + } onSendInput(input); }, diff --git a/src/ui/hooks/useDragToSystemDesktop.ts b/src/ui/hooks/useDragToSystemDesktop.ts index 3258876f..3f0f1368 100644 --- a/src/ui/hooks/useDragToSystemDesktop.ts +++ b/src/ui/hooks/useDragToSystemDesktop.ts @@ -59,7 +59,9 @@ export function useDragToSystemDesktop({ }; }); } - } catch (error) {} + } catch { + // IndexedDB not available or failed to retrieve directory + } return null; }; @@ -75,7 +77,9 @@ export function useDragToSystemDesktop({ store.put({ handle: dirHandle }, "lastSaveDir"); }; } - } catch (error) {} + } catch { + // Failed to save directory handle + } }; const isFileSystemAPISupported = () => { diff --git a/src/ui/main-axios.ts b/src/ui/main-axios.ts index f747e43d..f72fefdb 100644 --- a/src/ui/main-axios.ts +++ b/src/ui/main-axios.ts @@ -320,7 +320,7 @@ function isDev(): boolean { ); } -let apiHost = import.meta.env.VITE_API_HOST || "localhost"; +const apiHost = import.meta.env.VITE_API_HOST || "localhost"; let apiPort = 30001; let configuredServerUrl: string | null = null;