diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 377dfe0..de8fa36 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,9 @@ jobs: - name: Run unit tests run: npm test + - name: Lint + run: npm run lint + - name: Type-check run: npm run typecheck diff --git a/README.md b/README.md index 6b019e8..42350f0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Repository / 리포지토리: ### Quick start (Electron) -Requirements: Node.js 20+ (bundles Electron 42 / Node 24), Windows. +Requirements: Node.js 22+ (`node:sqlite` is required at build/test time; bundles Electron 42 / Node 24), Windows. ```powershell # Install dependencies (first time only) @@ -113,7 +113,7 @@ copilot-watchtower ### 빠른 시작 (Electron) -요구사항: Node.js 20+ (Electron 42 / Node 24 번들), Windows. +요구사항: Node.js 22+ (빌드/테스트에 `node:sqlite` 필요, Electron 42 / Node 24 번들), Windows. ```powershell # 의존성 설치 (최초 1회) diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..6b875ae --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,43 @@ +import js from '@eslint/js' +import tseslint from 'typescript-eslint' +import reactHooks from 'eslint-plugin-react-hooks' +import globals from 'globals' + +export default tseslint.config( + { ignores: ['out/**', 'dist/**', 'node_modules/**', 'legacy/**', '*.config.js'] }, + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['**/*.{ts,tsx}'], + languageOptions: { + parserOptions: { ecmaVersion: 'latest', sourceType: 'module' } + }, + rules: { + // Unused values are usually a leftover from an incomplete refactor — the + // dead ko-KR number formatters this config was added to catch, for example. + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + '@typescript-eslint/no-explicit-any': 'error', + 'no-console': ['warn', { allow: ['error'] }], + eqeqeq: ['error', 'smart'] + } + }, + { + files: ['src/main/**/*.ts', 'src/preload/**/*.ts'], + languageOptions: { globals: { ...globals.node } } + }, + { + files: ['src/renderer/**/*.{ts,tsx}'], + languageOptions: { globals: { ...globals.browser } }, + plugins: { 'react-hooks': reactHooks }, + rules: { + ...reactHooks.configs.recommended.rules, + // Stale-closure and missing-dependency bugs are the single most common + // class of defect in this renderer; treat them as errors, not hints. + 'react-hooks/exhaustive-deps': 'error' + } + }, + { + files: ['tests/**/*.ts', '**/*.test.ts'], + languageOptions: { globals: { ...globals.node } } + } +) diff --git a/package-lock.json b/package-lock.json index ea23a25..3c5f833 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,22 +14,31 @@ "i18next": "^26.3.3", "koffi": "^3.0.2", "lucide-react": "^0.460.0", + "pretendard": "^1.3.9", "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^17.0.8" }, "devDependencies": { + "@eslint/js": "^9.39.5", "@types/node": "^22.9.0", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.3", "@vitest/coverage-v8": "^4.1.10", "electron": "^42.5.0", - "electron-builder": "^25.1.8", + "electron-builder": "^26.15.3", "electron-vite": "^2.3.0", + "eslint": "^9.39.5", + "eslint-plugin-react-hooks": "^5.2.0", + "globals": "^15.15.0", "typescript": "^5.6.3", + "typescript-eslint": "^8.64.0", "vite": "^5.4.11", "vitest": "^4.1.10" + }, + "engines": { + "node": ">=22.5.0" } }, "node_modules/@azure/msal-common": { @@ -371,24 +380,6 @@ "node": ">=18" } }, - "node_modules/@develar/schema-utils": { - "version": "2.6.5", - "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", - "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.0", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/@electron-internal/extract-zip": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@electron-internal/extract-zip/-/extract-zip-1.0.4.tgz", @@ -401,8 +392,8 @@ }, "node_modules/@electron/asar": { "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", - "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha1-TpGWpLVPuhjFbNjVysZ8W9xYgGU=", "dev": true, "license": "MIT", "dependencies": { @@ -419,15 +410,15 @@ }, "node_modules/@electron/asar/node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, "node_modules/@electron/asar/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha1-cj06MMBVjCJavJ/Eeac+FOJsPC8=", "dev": true, "license": "MIT", "dependencies": { @@ -437,8 +428,8 @@ }, "node_modules/@electron/asar/node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha1-WAyI+NVEXyvWqo88re+g3nn71p4=", "dev": true, "license": "ISC", "dependencies": { @@ -448,6 +439,37 @@ "node": "*" } }, + "node_modules/@electron/fuses": { + "version": "1.8.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/fuses/-/fuses-1.8.0.tgz", + "integrity": "sha1-rTTTzEcDsSWLg/aYmRcFLPwUkKA=", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.1", + "fs-extra": "^9.0.1", + "minimist": "^1.2.5" + }, + "bin": { + "electron-fuses": "dist/bin.js" + } + }, + "node_modules/@electron/fuses/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha1-WVRGDHZKjaIJS6NVS/g55rmnyG0=", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@electron/get": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@electron/get/-/get-5.0.0.tgz", @@ -484,8 +506,8 @@ }, "node_modules/@electron/notarize": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", - "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/notarize/-/notarize-2.5.0.tgz", + "integrity": "sha1-1NJTVq36Kd9Kdr1kqL00cjfNJR4=", "dev": true, "license": "MIT", "dependencies": { @@ -499,8 +521,8 @@ }, "node_modules/@electron/notarize/node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha1-WVRGDHZKjaIJS6NVS/g55rmnyG0=", "dev": true, "license": "MIT", "dependencies": { @@ -514,9 +536,9 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", - "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", + "version": "1.3.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/osx-sign/-/osx-sign-1.3.3.tgz", + "integrity": "sha1-r3UVEEiDGNn3ZjaUr4WBlpDXVYM=", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -537,8 +559,8 @@ }, "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha1-DFteMMJVei8G/r03tzIpRqruQrM=", "dev": true, "license": "MIT", "engines": { @@ -549,55 +571,34 @@ } }, "node_modules/@electron/rebuild": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.1.tgz", - "integrity": "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==", + "version": "4.2.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/rebuild/-/rebuild-4.2.0.tgz", + "integrity": "sha1-7nQpqXE00T6ze39RfXN+AtHeqHc=", "dev": true, "license": "MIT", "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "node-abi": "^3.45.0", - "node-api-version": "^0.2.0", - "node-gyp": "^9.0.0", - "ora": "^5.1.0", - "read-binary-file-arch": "^1.0.6", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" + "node-abi": "^4.2.0", + "node-api-version": "^0.2.1", + "node-gyp": "^12.2.0", + "read-binary-file-arch": "^1.0.6" }, "bin": { "electron-rebuild": "lib/cli.js" }, "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/rebuild/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "node": ">=22.12.0" } }, "node_modules/@electron/universal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", - "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "version": "2.0.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/universal/-/universal-2.0.3.tgz", + "integrity": "sha1-FoDfbO2PEoyg/yTinCFl1B14s84=", "dev": true, "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.7", + "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", @@ -611,15 +612,15 @@ }, "node_modules/@electron/universal/node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha1-C7oicf631Fiw0xrRNiWqpHVEMeI=", "dev": true, "license": "MIT", "dependencies": { @@ -627,9 +628,9 @@ } }, "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "11.3.5", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", - "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "version": "11.3.6", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha1-98uA6d9VDNHbb1N/pc3VaNPnDRA=", "dev": true, "license": "MIT", "dependencies": { @@ -643,8 +644,8 @@ }, "node_modules/@electron/universal/node_modules/minimatch": { "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha1-mwy5/LeAh/b9fqur4lEcTT1gV04=", "dev": true, "license": "ISC", "dependencies": { @@ -657,6 +658,45 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@electron/windows-sign": { + "version": "1.2.2", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/windows-sign/-/windows-sign-1.2.2.tgz", + "integrity": "sha1-jOqtUtXB6xhwL0gQPV87x8M4+p0=", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "peer": true, + "dependencies": { + "cross-dirname": "^0.1.0", + "debug": "^4.3.4", + "fs-extra": "^11.1.1", + "minimist": "^1.2.8", + "postject": "^1.0.0-alpha.6" + }, + "bin": { + "electron-windows-sign": "bin/electron-windows-sign.js" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/windows-sign/node_modules/fs-extra": { + "version": "11.3.6", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-11.3.6.tgz", + "integrity": "sha1-98uA6d9VDNHbb1N/pc3VaNPnDRA=", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/@emnapi/core": { "version": "1.11.1", "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@emnapi/core/-/core-1.11.1.tgz", @@ -1136,114 +1176,326 @@ "node": ">=12" } }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha1-TpCvZ7xR3e5s3vUoTt9XLsN2tZU=", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha1-DNcv6FUOPC6uFWqWpN3c0cisWAA=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha1-vM32Fbz3tujbgw7AuNIcmiXeWXs=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha1-8p4iBXrVMWzyODbO6aNMgf/8t+Y=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha1-cj06MMBVjCJavJ/Eeac+FOJsPC8=", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha1-WAyI+NVEXyvWqo88re+g3nn71p4=", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=12" + "node": "*" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha1-G9AGzut+LlWyt3OrMY0wDhpmrto=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha1-dyJYIEE9lhdQnak0IZCiAZ54dhw=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.6", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/eslintrc/-/eslintrc-3.3.6.tgz", + "integrity": "sha1-0iv9azp9jh8sCy8ubeERtT7G4T4=", "dev": true, "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.3.0", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha1-B+mCx0YmFnqnoklcU4F4ktcTlJI=", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha1-cj06MMBVjCJavJ/Eeac+FOJsPC8=", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/globals/-/globals-14.0.0.tgz", + "integrity": "sha1-iY10E8Kbq89rr+Vvyt3thYrack4=", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha1-WAyI+NVEXyvWqo88re+g3nn71p4=", + "dev": true, + "license": "ISC", "dependencies": { - "ansi-regex": "^6.2.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=12" + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.5", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/js/-/js-9.39.5.tgz", + "integrity": "sha1-by+8/3VQDSKdU14KlJrhNHLIR4c=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "url": "https://eslint.org/donate" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha1-biEmoTR+hqTe34cG7Gf/jhB+u60=", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha1-l3nj/Zt+4zVxpXQ1z0M1oXlKbLI=", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" }, "engines": { - "node": ">=12" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha1-qCcsoDsqz0kmcCIrIyC2xCG/3mA=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha1-j4AMzME/T4zTEW4tnAqUk52j4+0=", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha1-8qCfYgEjkLK/8/xvskjd7IwJoJA=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha1-r1smkaIrRL6EewyoFkHF+2rQFyw=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha1-wrnS43TuYsWG062+qHGZsdenpro=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha1-LVmuOrSzj7QnC/oj0w+OLobH/jI=", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@jridgewell/gen-mapping": { @@ -1522,8 +1774,8 @@ }, "node_modules/@malept/cross-spawn-promise": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha1-0Hct4apoCgv7m6LzK0yCjHhXy50=", "dev": true, "funding": [ { @@ -1545,8 +1797,8 @@ }, "node_modules/@malept/flatpak-bundler": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", - "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha1-6KMsMKldIMKxu2NcxYCYGgY4mFg=", "dev": true, "license": "MIT", "dependencies": { @@ -1561,8 +1813,8 @@ }, "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha1-WVRGDHZKjaIJS6NVS/g55rmnyG0=", "dev": true, "license": "MIT", "dependencies": { @@ -1594,67 +1846,79 @@ "@emnapi/runtime": "^1.7.1" } }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "node_modules/@noble/hashes": { + "version": "2.2.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@noble/hashes/-/hashes-2.2.0.tgz", + "integrity": "sha1-ItodFqRplU/Oh3BV1VmQCmxztjs=", "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, + "license": "MIT", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "node_modules/@oxc-project/types": { + "version": "0.138.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@oxc-project/types/-/types-0.138.0.tgz", + "integrity": "sha1-zpaQ7IAUS0w43+1E52pnuRHfmso=", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" } }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", + "node_modules/@peculiar/asn1-schema": { + "version": "2.8.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@peculiar/asn1-schema/-/asn1-schema-2.8.0.tgz", + "integrity": "sha1-aWmfhCWbIWFgfKv8NOUSpAI9vvk=", + "dev": true, + "license": "MIT", + "dependencies": { + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha1-/mHoUlnjtbpa1WbLYsp1s9PNUzk=", "dev": true, "license": "MIT", "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" + "tslib": "^2.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=8.0.0" } }, - "node_modules/@oxc-project/types": { - "version": "0.138.0", - "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@oxc-project/types/-/types-0.138.0.tgz", - "integrity": "sha1-zpaQ7IAUS0w43+1E52pnuRHfmso=", + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha1-onykxLc2UuEQ8Zp9FtZk9FilUo4=", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" + "dependencies": { + "tslib": "^2.8.1" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "node_modules/@peculiar/webcrypto": { + "version": "1.7.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@peculiar/webcrypto/-/webcrypto-1.7.1.tgz", + "integrity": "sha1-74z66HjKHxpE7wyCzz+m88vpwmo=", "dev": true, "license": "MIT", - "optional": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/json-schema": "^1.1.12", + "@peculiar/utils": "^2.0.2", + "tslib": "^2.8.1", + "webcrypto-core": "^1.9.2" + }, "engines": { - "node": ">=14" + "node": ">=14.18.0" } }, "node_modules/@rolldown/binding-android-arm64": { @@ -2273,8 +2537,8 @@ }, "node_modules/@sindresorhus/is": { "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha1-PHycRuZ4/u/nouW7YJ09vWZf+z8=", "dev": true, "license": "MIT", "engines": { @@ -2293,8 +2557,8 @@ }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha1-tKkUu2LnwnLU5Zif5EQPgSqx2Ac=", "dev": true, "license": "MIT", "dependencies": { @@ -2304,16 +2568,6 @@ "node": ">=10" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", - "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", @@ -2372,8 +2626,8 @@ }, "node_modules/@types/cacheable-request": { "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha1-pDCzJgRmyntcpb/XNWk7Nuep0YM=", "dev": true, "license": "MIT", "dependencies": { @@ -2396,8 +2650,8 @@ }, "node_modules/@types/debug": { "version": "4.1.13", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", - "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha1-ItHMnVQtNZPK6nZPl0MGqzYobuc=", "dev": true, "license": "MIT", "dependencies": { @@ -2420,8 +2674,8 @@ }, "node_modules/@types/fs-extra": { "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha1-dZT7rgT+fxkYzos9IT90/0SsH0U=", "dev": true, "license": "MIT", "dependencies": { @@ -2430,15 +2684,22 @@ }, "node_modules/@types/http-cache-semantics": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha1-9qd4j0OMv94V8prK1GUStMAZE7M=", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha1-WWoXRyM2lNUPatinhp/Lb1bPWEE=", "dev": true, "license": "MIT" }, "node_modules/@types/keyv": { "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha1-PM2xxnUbDH5SMAvNrNW8v4+qdbY=", "dev": true, "license": "MIT", "dependencies": { @@ -2447,8 +2708,8 @@ }, "node_modules/@types/ms": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha1-BSqmekjszEMJ1/AZG35BQ0uQu3g=", "dev": true, "license": "MIT" }, @@ -2462,18 +2723,6 @@ "undici-types": "~6.21.0" } }, - "node_modules/@types/plist": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", - "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*", - "xmlbuilder": ">=11.0.1" - } - }, "node_modules/@types/prop-types": { "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", @@ -2504,21 +2753,269 @@ }, "node_modules/@types/responselike": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha1-zClwbwo5fP5t+J3r/kv1zqFZ21A=", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/@types/verror": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", - "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.64.0.tgz", + "integrity": "sha1-caDD1fil5sXf208PBL0b+1ctXiQ=", "dev": true, "license": "MIT", - "optional": true + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.64.0", + "@typescript-eslint/type-utils": "8.64.0", + "@typescript-eslint/utils": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.64.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha1-aleq70yQ3yesNZCHXSno8RmIyI4=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.64.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/parser/-/parser-8.64.0.tgz", + "integrity": "sha1-yYZKHMKKE/8ppzFPve8FKLsSL3I=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.64.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/project-service/-/project-service-8.64.0.tgz", + "integrity": "sha1-FMTik5DXMlp/ihIYwniP1km4XaY=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.64.0", + "@typescript-eslint/types": "^8.64.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/scope-manager/-/scope-manager-8.64.0.tgz", + "integrity": "sha1-1F8VMEqUyFw52zF7cXsVj7YlmVg=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.64.0.tgz", + "integrity": "sha1-xirI6pFzw8rIs4uOZuMKBGtUiFE=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/type-utils/-/type-utils-8.64.0.tgz", + "integrity": "sha1-EG+n1Yz5z3dY892OQmrII37OrPM=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0", + "@typescript-eslint/utils": "8.64.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/types/-/types-8.64.0.tgz", + "integrity": "sha1-tB+O9d1AYWkIZYuZEZep1IbNpgs=", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.64.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/typescript-estree/-/typescript-estree-8.64.0.tgz", + "integrity": "sha1-uNUSVeLXJutL2A05ek+0FwwC7sw=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.64.0", + "@typescript-eslint/tsconfig-utils": "8.64.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/visitor-keys": "8.64.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-7.8.5.tgz", + "integrity": "sha1-ObZGA33VDBT7RR5+TKxY7YuGP2k=", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/utils/-/utils-8.64.0.tgz", + "integrity": "sha1-mLsgEM+3VLQZhbnJPm6LPc171gA=", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.64.0", + "@typescript-eslint/types": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.64.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@typescript-eslint/visitor-keys/-/visitor-keys-8.64.0.tgz", + "integrity": "sha1-eghCHRDlSWBzM1LNfJX6sXhOhHM=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.64.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha1-njyUiWl4JNLUzjqK0SYo+R6fWb4=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/@vitejs/plugin-react": { "version": "4.7.0", @@ -2659,28 +3156,47 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.9.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", - "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "version": "0.8.13", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha1-ANHdlAshjf8uSTCdQQ2LshIVkiU=", "dev": true, "license": "MIT", "engines": { - "node": ">=14.6" + "node": ">=10.0.0" } }, - "node_modules/7zip-bin": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", - "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "node_modules/abbrev": { + "version": "4.0.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/abbrev/-/abbrev-4.0.0.tgz", + "integrity": "sha1-7JM/Die2zWDom1xrKjBK9CIJuwU=", "dev": true, - "license": "MIT" + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha1-F4WtuE+vjYrdEDabk4Jvwr0I8f4=", "dev": true, - "license": "ISC" + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha1-ftW7VZCLOy8bxVxq8WU7rafweTc=", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, "node_modules/adler-32": { "version": "1.3.1", @@ -2693,72 +3209,35 @@ }, "node_modules/agent-base": { "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha1-48121MVI7oldPD/Y3B9sW5Ay56g=", "dev": true, "license": "MIT", "engines": { "node": ">= 14" } }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "version": "8.20.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha1-MEs2Nq3Yi6fZNnYN1Q7OAG3qlfk=", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "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/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ=", "dev": true, "license": "MIT", "engines": { @@ -2767,8 +3246,8 @@ }, "node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha1-7dgDYornHATIWuegkG7a00tkiTc=", "dev": true, "license": "MIT", "dependencies": { @@ -2781,191 +3260,189 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/app-builder-bin": { - "version": "5.0.0-alpha.10", - "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz", - "integrity": "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==", - "dev": true, - "license": "MIT" - }, "node_modules/app-builder-lib": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.1.8.tgz", - "integrity": "sha512-pCqe7dfsQFBABC1jeKZXQWhGcCPF3rPCXDdfqVKjIeWBcXzyC1iOWZdfFhGl+S9MyE/k//DFmC6FzuGAUudNDg==", + "version": "26.15.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/app-builder-lib/-/app-builder-lib-26.15.3.tgz", + "integrity": "sha1-D6bJZeMHu22GImQHx1CkWz/Wsb8=", "dev": true, "license": "MIT", "dependencies": { - "@develar/schema-utils": "~2.6.5", + "@electron/asar": "3.4.1", + "@electron/fuses": "^1.8.0", + "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", - "@electron/osx-sign": "1.3.1", - "@electron/rebuild": "3.6.1", - "@electron/universal": "2.0.1", + "@electron/osx-sign": "1.3.3", + "@electron/rebuild": "^4.0.4", + "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", + "@noble/hashes": "^2.2.0", + "@peculiar/webcrypto": "^1.7.1", "@types/fs-extra": "9.0.13", + "ajv": "^8.18.0", + "asn1js": "^3.0.10", "async-exit-hook": "^2.0.1", - "bluebird-lst": "^1.0.9", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", + "builder-util": "26.15.3", + "builder-util-runtime": "9.7.0", "chromium-pickle-js": "^0.2.0", - "config-file-ts": "0.2.8-rc1", + "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", - "electron-publish": "25.1.7", - "form-data": "^4.0.0", + "electron-publish": "26.15.3", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", - "is-ci": "^3.0.0", "isbinaryfile": "^5.0.0", + "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", - "minimatch": "^10.0.0", + "minimatch": "^10.2.5", + "pkijs": "^3.4.0", + "plist": "3.1.0", + "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", - "sanitize-filename": "^1.6.3", - "semver": "^7.3.8", - "tar": "^6.1.12", - "temp-file": "^3.4.0" + "semver": "~7.7.3", + "tar": "^7.5.7", + "temp-file": "^3.4.0", + "tiny-async-pool": "1.3.0", + "unzipper": "^0.12.3", + "which": "^5.0.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "25.1.8", - "electron-builder-squirrel-windows": "25.1.8" + "dmg-builder": "26.15.3", + "electron-builder-squirrel-windows": "26.15.3" } }, - "node_modules/app-builder-lib/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "node_modules/app-builder-lib/node_modules/@electron/get": { + "version": "3.1.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@electron/get/-/get-3.1.0.tgz", + "integrity": "sha1-IsWgvZF6sgG63rd7xK0Yy6VMtOw=", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" } }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "dev": true, - "license": "ISC" - }, - "node_modules/archiver": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", - "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">= 10" + "node": ">=6 <7 || >=8" } }, - "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "node_modules/app-builder-lib/node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-6.3.1.tgz", + "integrity": "sha1-VW0u+GiRRuRtzqS/3QlfNDTf/LQ=", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/app-builder-lib/node_modules/ci-info": { + "version": "4.3.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha1-NVrVcZIIELViPhHUAjL0Q/FvHao=", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], "license": "MIT", - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/archiver-utils/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "node_modules/app-builder-lib/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha1-QgOZ1BbOH76bwKB8Yvpo1n/Q+PI=", "dev": true, "license": "MIT", - "peer": true + "engines": { + "node": ">=6" + } }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.4", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-7.7.4.tgz", + "integrity": "sha1-KEZONgYOmR+noR0CedLT87V6foo=", "dev": true, "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" } }, "node_modules/argparse": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha1-JG9Q88p4oyQPbJl+ipvR6sSeSzg=", "dev": true, "license": "Python-2.0" }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/asn1js": { + "version": "3.0.10", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha1-3ybIdMiotBymBe/qR7KtB1UQE90=", "dev": true, - "license": "MIT", - "optional": true, + "license": "BSD-3-Clause", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.5", + "tslib": "^2.8.1" + }, "engines": { - "node": ">=0.8" + "node": ">=12.0.0" } }, "node_modules/assertion-error": { @@ -2997,28 +3474,17 @@ "dev": true, "license": "MIT" }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, "node_modules/async": { "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/async/-/async-3.2.6.tgz", + "integrity": "sha1-Gwco4Ukp1RuFtEm38G4nwRReOM4=", "dev": true, "license": "MIT" }, "node_modules/async-exit-hook": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", - "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha1-i9iwJLDsmxwBzMua+dspvXF9+vM=", "dev": true, "license": "MIT", "engines": { @@ -3027,25 +3493,32 @@ }, "node_modules/asynckit": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true, "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha1-YCzUtG6EStTv/JKoARo8RuAjjcI=", "dev": true, "license": "ISC", "engines": { "node": ">= 4.0.0" } }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha1-CqFnIWllrJR0zPqDiSz7az4eUu8=", + "dev": true, + "license": "MIT" + }, "node_modules/balanced-match": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha1-v7EGYv7tgZaixi58aOF3IMJ0F5o=", "dev": true, "license": "MIT", "engines": { @@ -3054,8 +3527,8 @@ }, "node_modules/base64-js": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha1-GxtEAWClv3rUC2UPCVljSBkDkwo=", "dev": true, "funding": [ { @@ -3086,39 +3559,26 @@ "node": ">=6.0.0" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "node_modules/bluebird": { "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha1-nyKcFb4nJFT/qXOs4NvueaGww28=", "dev": true, "license": "MIT" }, - "node_modules/bluebird-lst": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", - "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha1-nlKUr06YMUSUy7F5efpUyhWfEWs=", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", "dev": true, "license": "MIT", - "dependencies": { - "bluebird": "^3.5.5" - } + "optional": true }, "node_modules/brace-expansion": { "version": "5.0.7", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", - "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha1-Gw5GlltHna1lr3N7SgJ5CgVJgzc=", "dev": true, "license": "MIT", "dependencies": { @@ -3162,42 +3622,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": "*" - } - }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3206,40 +3630,41 @@ }, "node_modules/buffer-from": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha1-KxRqb9cugLT1XSVfNe1Zo6mkG9U=", "dev": true, "license": "MIT" }, "node_modules/builder-util": { - "version": "25.1.7", - "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-25.1.7.tgz", - "integrity": "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==", + "version": "26.15.3", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/builder-util/-/builder-util-26.15.3.tgz", + "integrity": "sha1-Huqzfw1KZCH+GM6ds4ztWIgdlRk=", "dev": true, "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", - "7zip-bin": "~5.2.0", - "app-builder-bin": "5.0.0-alpha.10", - "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.2.10", + "builder-util-runtime": "9.7.0", "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", + "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", - "is-ci": "^3.0.0", "js-yaml": "^4.1.0", + "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", - "temp-file": "^3.4.0" + "temp-file": "^3.4.0", + "tiny-async-pool": "1.3.0" + }, + "engines": { + "node": ">=14.0.0" } }, "node_modules/builder-util-runtime": { - "version": "9.2.10", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz", - "integrity": "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==", + "version": "9.7.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/builder-util-runtime/-/builder-util-runtime-9.7.0.tgz", + "integrity": "sha1-yG+6MDaE6Hfa7hXCnu3oGYcWb+8=", "dev": true, "license": "MIT", "dependencies": { @@ -3250,6 +3675,16 @@ "node": ">=12.0.0" } }, + "node_modules/bytestreamjs": { + "version": "2.0.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/bytestreamjs/-/bytestreamjs-2.0.1.tgz", + "integrity": "sha1-oylHx844mm+hGgmppWPQpFiJU14=", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -3260,101 +3695,10 @@ "node": ">=8" } }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/cacheable-lookup": { "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha1-WmuGWyxENXvj1evCpGewMnGacAU=", "dev": true, "license": "MIT", "engines": { @@ -3363,8 +3707,8 @@ }, "node_modules/cacheable-request": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha1-ejPr8IYTF4tANjW+e4mdPmm76Bc=", "dev": true, "license": "MIT", "dependencies": { @@ -3382,8 +3726,8 @@ }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha1-S1QowiK+mF15w9gmV0edvgtZstY=", "dev": true, "license": "MIT", "dependencies": { @@ -3394,6 +3738,16 @@ "node": ">= 0.4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001799", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", @@ -3440,8 +3794,8 @@ }, "node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha1-qsTit3NKdAhnrrFr8CqtVWoeegE=", "dev": true, "license": "MIT", "dependencies": { @@ -3456,26 +3810,26 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "version": "3.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha1-mFXmTs0kCpzEJnzopKpdJKHaFeQ=", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/chromium-pickle-js": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", "dev": true, "license": "MIT" }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.4.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha1-fVTv+fVLRbYkAcJgMmlutZyL0Yw=", "dev": true, "funding": [ { @@ -3488,64 +3842,10 @@ "node": ">=8" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha1-DASwddsCy/5g3I5s8vVIaxo2CKo=", "dev": true, "license": "ISC", "dependencies": { @@ -3557,20 +3857,10 @@ "node": ">=12" } }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, "node_modules/clone-response": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha1-ryAyqkeBY5nPXwodDbkC9ReruMM=", "dev": true, "license": "MIT", "dependencies": { @@ -3582,8 +3872,8 @@ }, "node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha1-ctOmjVmMm9s68q0ehPIdiWq9TeM=", "dev": true, "license": "MIT", "dependencies": { @@ -3595,25 +3885,15 @@ }, "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha1-wqCah6y95pVD3m9j+jmVyCbFNqI=", "dev": true, "license": "MIT" }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/combined-stream": { "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha1-w9RaizT9cwYxoRCoolIGgrMdWn8=", "dev": true, "license": "MIT", "dependencies": { @@ -3625,8 +3905,8 @@ }, "node_modules/commander": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/commander/-/commander-5.1.0.tgz", + "integrity": "sha1-Rqu9FlL44Fm92u+Zu9yyrZzxea4=", "dev": true, "license": "MIT", "engines": { @@ -3635,146 +3915,35 @@ }, "node_modules/compare-version": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/compress-commons": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", - "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "license": "MIT" }, - "node_modules/config-file-ts": { - "version": "0.2.8-rc1", - "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", - "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^10.3.12", - "typescript": "^5.4.3" - } - }, - "node_modules/config-file-ts/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/config-file-ts/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/config-file-ts/node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "version": "1.0.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha1-pgQtNjTCsn6TKPg3uWX6yDgI24U=", "dev": true, "license": "MIT" }, - "node_modules/crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "buffer": "^5.1.0" - } - }, "node_modules/crc-32": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", @@ -3787,25 +3956,19 @@ "node": ">=0.8" } }, - "node_modules/crc32-stream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", - "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "node_modules/cross-dirname": { + "version": "0.1.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cross-dirname/-/cross-dirname-0.1.0.tgz", + "integrity": "sha1-uJlZnzClOJ9Z54wVDhn5V60Wo3w=", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } + "optional": true, + "peer": true }, "node_modules/cross-spawn": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha1-ilj+ePANzXDDcEUXWd+/rwPo7p8=", "dev": true, "license": "MIT", "dependencies": { @@ -3817,6 +3980,29 @@ "node": ">= 8" } }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true, + "license": "ISC" + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/which/-/which-2.0.2.tgz", + "integrity": "sha1-fGqN0KY2oDJ+ELWckobu6T8/UbE=", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -3844,8 +4030,8 @@ }, "node_modules/decompress-response": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha1-yjh2Et234QS9FthaqwDV7PCcZvw=", "dev": true, "license": "MIT", "dependencies": { @@ -3860,8 +4046,8 @@ }, "node_modules/decompress-response/node_modules/mimic-response": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha1-LR1Zr5wbEpgVrMwsRqAipc4fo8k=", "dev": true, "license": "MIT", "engines": { @@ -3871,46 +4057,71 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha1-pvLc5hL63S7x9Rm3NVHxfoUZmDE=", + "dev": true, + "license": "MIT" + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha1-gBa9tBQ+RjK3ejRJxiNid95SBYc=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha1-iU3BQbt9MGCuQ2b2oBB+aPvkjF4=", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "clone": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha1-EHgcxhbrlRqAoDS6/Kpzd/avK2w=", "dev": true, "license": "MIT", + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/delayed-stream": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" } }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -3921,10 +4132,18 @@ "node": ">=8" } }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha1-yccHdaScPQO8LAbZpzvlUPl4+LE=", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/dir-compare": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", - "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/dir-compare/-/dir-compare-4.2.0.tgz", + "integrity": "sha1-0dSZnBT79VKBBx/a5Ck7O5zobxk=", "dev": true, "license": "MIT", "dependencies": { @@ -3934,15 +4153,15 @@ }, "node_modules/dir-compare/node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, "node_modules/dir-compare/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha1-cj06MMBVjCJavJ/Eeac+FOJsPC8=", "dev": true, "license": "MIT", "dependencies": { @@ -3952,8 +4171,8 @@ }, "node_modules/dir-compare/node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha1-WAyI+NVEXyvWqo88re+g3nn71p4=", "dev": true, "license": "ISC", "dependencies": { @@ -3964,54 +4183,22 @@ } }, "node_modules/dmg-builder": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.8.tgz", - "integrity": "sha512-NoXo6Liy2heSklTI5OIZbCgXC1RzrDQsZkeEwXhdOro3FT1VBOvbubvscdPnjVuQ4AMwwv61oaH96AbiYg9EnQ==", + "version": "26.15.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/dmg-builder/-/dmg-builder-26.15.3.tgz", + "integrity": "sha1-2IQ2LiI1Ue4NvJa7txh7QpBTePg=", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "25.1.8", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", "fs-extra": "^10.1.0", - "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" - }, - "optionalDependencies": { - "dmg-license": "^1.0.11" - } - }, - "node_modules/dmg-license": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", - "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "@types/plist": "^3.0.1", - "@types/verror": "^1.10.3", - "ajv": "^6.10.0", - "crc": "^3.8.0", - "iconv-corefoundation": "^1.1.7", - "plist": "^3.0.4", - "smart-buffer": "^4.0.2", - "verror": "^1.10.0" - }, - "bin": { - "dmg-license": "bin/dmg-license.js" - }, - "engines": { - "node": ">=8" } }, "node_modules/dotenv": { "version": "16.6.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", - "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha1-dz8OaVJ6gxXHKF1e5zxEWdIKgCA=", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -4023,8 +4210,8 @@ }, "node_modules/dotenv-expand": { "version": "11.0.7", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", - "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha1-r2la6gB9b9yEyGzY0K1760CgvQg=", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -4039,8 +4226,8 @@ }, "node_modules/dunder-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha1-165mfh3INIL4tw/Q9u78UNow9Yo=", "dev": true, "license": "MIT", "dependencies": { @@ -4052,12 +4239,15 @@ "node": ">= 0.4" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", @@ -4070,8 +4260,8 @@ }, "node_modules/ejs": { "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha1-aauDWLFOiW+AzDnmIIe4hQDDrDs=", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4104,19 +4294,19 @@ } }, "node_modules/electron-builder": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-25.1.8.tgz", - "integrity": "sha512-poRgAtUHHOnlzZnc9PK4nzG53xh74wj2Jy7jkTrqZ0MWPoHGh1M2+C//hGeYdA+4K8w4yiVCNYoLXF7ySj2Wig==", + "version": "26.15.3", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/electron-builder/-/electron-builder-26.15.3.tgz", + "integrity": "sha1-DoKCj2gpwLJZYzg2UgkXCsCsvNU=", "dev": true, "license": "MIT", "dependencies": { - "app-builder-lib": "25.1.8", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", + "builder-util-runtime": "9.7.0", "chalk": "^4.1.2", - "dmg-builder": "25.1.8", + "ci-info": "^4.2.0", + "dmg-builder": "26.15.3", "fs-extra": "^10.1.0", - "is-ci": "^3.0.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" @@ -4130,30 +4320,31 @@ } }, "node_modules/electron-builder-squirrel-windows": { - "version": "25.1.8", - "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-25.1.8.tgz", - "integrity": "sha512-2ntkJ+9+0GFP6nAISiMabKt6eqBB0kX1QqHNWFWAXgi0VULKGisM46luRFpIBiU3u/TDmhZMM8tzvo2Abn3ayg==", + "version": "26.15.3", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.15.3.tgz", + "integrity": "sha1-vnGFQfXOLrDTRh8Pzdmn/Z3+ACo=", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "app-builder-lib": "25.1.8", - "archiver": "^5.3.1", - "builder-util": "25.1.7", - "fs-extra": "^10.1.0" + "app-builder-lib": "26.15.3", + "builder-util": "26.15.3", + "electron-winstaller": "5.4.0" } }, "node_modules/electron-publish": { - "version": "25.1.7", - "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz", - "integrity": "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==", + "version": "26.15.3", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/electron-publish/-/electron-publish-26.15.3.tgz", + "integrity": "sha1-22VkIHC/YMe9JtYHRBUGiR060FQ=", "dev": true, "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "25.1.7", - "builder-util-runtime": "9.2.10", + "aws4": "^1.13.2", + "builder-util": "26.15.3", + "builder-util-runtime": "9.7.0", "chalk": "^4.1.2", + "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" @@ -4196,6 +4387,66 @@ } } }, + "node_modules/electron-winstaller": { + "version": "5.4.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/electron-winstaller/-/electron-winstaller-5.4.0.tgz", + "integrity": "sha1-8GYNR21cT1ef337dLwzwHVTE0LI=", + "dev": true, + "hasInstallScript": true, + "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": ">=8.0.0" + }, + "optionalDependencies": { + "@electron/windows-sign": "^1.1.2" + } + }, + "node_modules/electron-winstaller/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha1-TxicRKoSO4lfcigE9V6iPq3DSOk=", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/electron-winstaller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "license": "MIT", + "peer": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-winstaller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY=", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/electron/node_modules/@types/node": { "version": "24.13.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.2.tgz", @@ -4215,26 +4466,15 @@ }, "node_modules/emoji-regex": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha1-6Bj9ac5cz8tARZT4QpY79TFkzDc=", "dev": true, "license": "MIT" }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha1-c0TXEd6kDgt0q8LtSXeHQ8ztsIw=", "dev": true, "license": "MIT", "dependencies": { @@ -4256,15 +4496,15 @@ }, "node_modules/err-code": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha1-I8Lzt1b/38YI0w4nyalBAkgH5/k=", "dev": true, "license": "MIT" }, "node_modules/es-define-property": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha1-mD6y+aZyTpMD9hrd8BHHLgngsPo=", "dev": true, "license": "MIT", "engines": { @@ -4273,8 +4513,8 @@ }, "node_modules/es-errors": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha1-BfdaJdq5jk+x3NXhRywFRtUFfI8=", "dev": true, "license": "MIT", "engines": { @@ -4290,8 +4530,8 @@ }, "node_modules/es-object-atoms": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha1-otCzcyBXJN+lJdI7DD4bHKWCyZs=", "dev": true, "license": "MIT", "dependencies": { @@ -4303,8 +4543,8 @@ }, "node_modules/es-set-tostringtag": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha1-8x274MGDsAptJutjJcgQwP0YvU0=", "dev": true, "license": "MIT", "dependencies": { @@ -4314,56 +4554,289 @@ "hasown": "^2.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha1-njr0B0Wd7tR+mpH5uIWoTrBcVh0=", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha1-FLqDpdNz49MR5a/KKc9b+tllvzQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/eslint/-/eslint-9.39.5.tgz", + "integrity": "sha1-Kk48iw91MZbvrpQ8j/qocw/Go/o=", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.6", + "@eslint/js": "9.39.5", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha1-G+AICQHmrDHOeXG+7T0+wKQj2eM=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha1-iOZGogf61hQ2/6OetQUUcgBlXII=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha1-TP6mD+fdCtjoFuHtAmwdUlG1EsE=", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha1-B+mCx0YmFnqnoklcU4F4ktcTlJI=", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha1-cj06MMBVjCJavJ/Eeac+FOJsPC8=", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha1-afaofZUTq4u4/mO9sJecRI5oRmA=", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha1-WAyI+NVEXyvWqo88re+g3nn71p4=", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/espree/-/espree-10.4.0.tgz", + "integrity": "sha1-1U9JSdRikAWh+haNk3w/8ffiqDc=", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha1-CNBI8mHw3e21uulfRoCUY9nJSW0=", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha1-eteWTWeauyi+5yzsY3WLHF0smSE=", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" }, "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "node": ">=4.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha1-LupSkHAvJquP5TcDcP+GyWXSESM=", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "engines": { - "node": ">=6" + "node": ">=4.0" } }, "node_modules/estree-walker": { @@ -4376,6 +4849,16 @@ "@types/estree": "^1.0.0" } }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q=", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expect-type": { "version": "1.4.0", "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/expect-type/-/expect-type-1.4.0.tgz", @@ -4388,36 +4871,49 @@ }, "node_modules/exponential-backoff": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha1-Uc+SwcBJPHZgU/nTq+5ENMJE0vY=", "dev": true, "license": "Apache-2.0" }, - "node_modules/extsprintf": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", - "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "optional": true - }, "node_modules/fast-deep-equal": { "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha1-On1WtVnWy8PrUSMlJE5hmmXGxSU=", "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha1-h0v2nG9ATCtdmcSBNBOZ/VWJJjM=", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.3", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fast-uri/-/fast-uri-3.1.3.tgz", + "integrity": "sha1-9pWkDwBqulBWMVc6ACHdshGUrRE=", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fdir/-/fdir-6.5.0.tgz", @@ -4436,10 +4932,23 @@ } } }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha1-d4e93PETG/+5JjbGlFe7wO3W2B8=", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/filelist": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", - "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha1-HohwlCp8Y2yGL3xJuTlJN7aplaM=", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4448,15 +4957,15 @@ }, "node_modules/filelist/node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-2.1.2.tgz", + "integrity": "sha1-C7oicf631Fiw0xrRNiWqpHVEMeI=", "dev": true, "license": "MIT", "dependencies": { @@ -4465,8 +4974,8 @@ }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha1-EpPvFdsAmLOUVA6Pn3RPn9qN7ks=", "dev": true, "license": "ISC", "dependencies": { @@ -4476,40 +4985,48 @@ "node": ">=10" } }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha1-TJKBnstwg1YeT0okCoa+UZj1Nvw=", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=14" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha1-Ds45/LFO4BL0sEEL0z3ZwfAREnw=", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=16" } }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha1-9cI8EH8PN96NvfJPE3IrO5jVJyY=", + "dev": true, + "license": "ISC" + }, "node_modules/form-data": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha1-KOhk4beG2+u2jbH0UvljUnhmWCc=", "dev": true, "license": "MIT", "dependencies": { @@ -4523,18 +5040,10 @@ "node": ">= 6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/fs-extra": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha1-Aoc8+8QITd4SfqpfmQXu8jJdGr8=", "dev": true, "license": "MIT", "dependencies": { @@ -4546,23 +5055,10 @@ "node": ">=12" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "license": "ISC" }, @@ -4583,35 +5079,14 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha1-LALYZNl/PqbIgwxGTL0Rq26rehw=", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4624,8 +5099,8 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha1-T5RBKoLbMvNuOwuXQfipf+sDH34=", "dev": true, "license": "ISC", "engines": { @@ -4634,8 +5109,8 @@ }, "node_modules/get-intrinsic": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha1-dD8OO2lkqTpUke0b/6rgVNf5jQE=", "dev": true, "license": "MIT", "dependencies": { @@ -4659,8 +5134,8 @@ }, "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha1-FQs/J0OGnvPoUewMSdFbHRTQDuE=", "dev": true, "license": "MIT", "dependencies": { @@ -4673,8 +5148,8 @@ }, "node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha1-SWaheV7lrOZecGxLe+txJX1uItM=", "dev": true, "license": "MIT", "dependencies": { @@ -4689,8 +5164,8 @@ }, "node_modules/glob": { "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/glob/-/glob-7.2.3.tgz", + "integrity": "sha1-uN8PuAK7+o6JvR2Ti04WV47UTys=", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", @@ -4709,17 +5184,30 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha1-bSN9mQg5UMeSkPJMdkKj3poo+eM=", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/glob/node_modules/balanced-match": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha1-6D46fj8wCzTLnYf2FfoMvzV2kO4=", "dev": true, "license": "MIT" }, "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.16", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha1-cj06MMBVjCJavJ/Eeac+FOJsPC8=", "dev": true, "license": "MIT", "dependencies": { @@ -4729,8 +5217,8 @@ }, "node_modules/glob/node_modules/minimatch": { "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha1-WAyI+NVEXyvWqo88re+g3nn71p4=", "dev": true, "license": "ISC", "dependencies": { @@ -4740,10 +5228,74 @@ "node": "*" } }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha1-rnzTG9NYO5PFoWQ3oa/ifMM6GrY=", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-7.8.5.tgz", + "integrity": "sha1-ObZGA33VDBT7RR5+TKxY7YuGP2k=", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/globals/-/globals-15.15.0.tgz", + "integrity": "sha1-fEdhKZ1BwysHVxWkzh7eeJf/cqg=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha1-dDDtOpddl7+1m8zkH1yruvplEjY=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gopd": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha1-ifVrghe9vIgCvSmd9tfxCB1+UaE=", "dev": true, "license": "MIT", "engines": { @@ -4755,8 +5307,8 @@ }, "node_modules/got": { "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/got/-/got-11.8.6.tgz", + "integrity": "sha1-J26Cfq2Hcu3bz8lxcFkLhBgjIzo=", "dev": true, "license": "MIT", "dependencies": { @@ -4796,10 +5348,24 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha1-lj7X0HHce/XwhMW/vg0bYiJYaFQ=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha1-/JxqeDoISVHQuXH+EBjegTcHozg=", "dev": true, "license": "MIT", "engines": { @@ -4811,8 +5377,8 @@ }, "node_modules/has-tostringtag": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha1-LNxC1AvvLltO6rfAGnPFTOerWrw=", "dev": true, "license": "MIT", "dependencies": { @@ -4825,17 +5391,10 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, "node_modules/hasown": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha1-jGLYy5C+sqrV0KW2dYGtmFTD8AM=", "dev": true, "license": "MIT", "dependencies": { @@ -4847,8 +5406,8 @@ }, "node_modules/hosted-git-info": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha1-gnuChn6f8cjQxNnVOIA5fSyG0iQ=", "dev": true, "license": "ISC", "dependencies": { @@ -4860,8 +5419,8 @@ }, "node_modules/hosted-git-info/node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha1-bW/mVw69lqr5D8rR2vo7JWbbOpQ=", "dev": true, "license": "ISC", "dependencies": { @@ -4873,8 +5432,8 @@ }, "node_modules/hosted-git-info/node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha1-m7knkNnA7/7GO+c1GeEaNQGaOnI=", "dev": true, "license": "ISC" }, @@ -4896,15 +5455,15 @@ }, "node_modules/http-cache-semantics": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha1-IF9Ntk+FYrdqT/kjWqUnmDmgndU=", "dev": true, "license": "BSD-2-Clause" }, "node_modules/http-proxy-agent": { "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha1-mosfJGhmwChQlIZYX2K48sGMJw4=", "dev": true, "license": "MIT", "dependencies": { @@ -4917,8 +5476,8 @@ }, "node_modules/http2-wrapper": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha1-uPVeDB8l1OvQizsMLAeflZCACz0=", "dev": true, "license": "MIT", "dependencies": { @@ -4931,8 +5490,8 @@ }, "node_modules/https-proxy-agent": { "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha1-2o3+rH2hMLBcK6S1nJts1mYRprk=", "dev": true, "license": "MIT", "dependencies": { @@ -4943,16 +5502,6 @@ "node": ">= 14" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, "node_modules/i18next": { "version": "26.3.3", "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.3.tgz", @@ -4981,89 +5530,47 @@ } } }, - "node_modules/iconv-corefoundation": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", - "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha1-PNQOcp82Q/2HywTlC/DrcivFlvU=", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "cli-truncate": "^2.1.0", - "node-addon-api": "^1.6.3" - }, "engines": { - "node": "^8.11.2 || >=10" + "node": ">= 4" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha1-nOy1ZQPAraHydB271lRuSxO1fM8=", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/imurmurhash": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, "node_modules/inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", @@ -5074,86 +5581,55 @@ }, "node_modules/inherits": { "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=", "dev": true, "license": "ISC" }, - "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-ci": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", - "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ci-info": "^3.2.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha1-8Rb4Bk/pCz94RKOJl8C3UFEmnx0=", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha1-ZPYeQsu7LuwgcanawLKLoeZdUIQ=", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "is-extglob": "^2.1.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10.0" } }, "node_modules/isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/isbinaryfile": { "version": "5.0.7", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", - "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha1-Gac/IoG3No3KnTs6yKBDQHRnCXk=", "dev": true, "license": "MIT", "engines": { @@ -5164,11 +5640,14 @@ } }, "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "version": "3.1.5", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha1-QuNo9o1eENrf7k/ae1ULwtiJLck=", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -5209,26 +5688,10 @@ "node": ">=8" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/jake": { "version": "10.9.4", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", - "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/jake/-/jake-10.9.4.tgz", + "integrity": "sha1-1ibaEIxj1c+wCrXCX63H4AhK+OY=", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5243,6 +5706,16 @@ "node": ">=10" } }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha1-l0Io8vTKK8IYhaF5e0X+po6VDGQ=", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5251,8 +5724,8 @@ }, "node_modules/js-yaml": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha1-0ZAFcqf3zwtfVAyDZz5gutNDZZI=", "dev": true, "funding": [ { @@ -5287,18 +5760,33 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha1-kziAKjDTtmBfvgYT4JQAjKjAWhM=", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "version": "1.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha1-rnvLNlard6c7pcSb9lTzjmtoYOI=", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true, "license": "MIT" }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true, + "license": "ISC", + "optional": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -5314,8 +5802,8 @@ }, "node_modules/jsonfile": { "version": "6.2.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", - "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha1-tuMXF/Isw3MwsIHOAFHtXeU68vY=", "dev": true, "license": "MIT", "dependencies": { @@ -5382,8 +5870,8 @@ }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha1-qHmpnilFL5QkOfKkBeOvizHU3pM=", "dev": true, "license": "MIT", "dependencies": { @@ -5418,59 +5906,23 @@ }, "node_modules/lazy-val": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", - "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha1-bPO59bwxzufuPjacCDK3WD3Nkj0=", "dev": true, "license": "MIT" }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/levn/-/levn-0.4.1.tgz", + "integrity": "sha1-rkViwAdHO5MqYgDUAyaN0v/8at4=", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "readable-stream": "^2.0.5" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.0" + "node": ">= 0.8.0" } }, "node_modules/lightningcss": { @@ -5734,36 +6186,28 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha1-VTIeswn+u8WcSAHZMackUqaB0oY=", "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha1-/ytmwfYybVlRPeJAe/iBQ5gSdxw=", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/lodash.includes": { "version": "4.3.0", @@ -5801,37 +6245,19 @@ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", "license": "MIT" }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha1-VYqlO0O2YeGSWgr9+japoQhf5Xo=", + "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.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -5846,8 +6272,8 @@ }, "node_modules/lowercase-keys": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha1-JgPni3tLAAbLyi+8yKMgJVislHk=", "dev": true, "license": "MIT", "engines": { @@ -5924,90 +6350,24 @@ "node": ">=10" } }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha1-vZBg9MW3CqgEHMxvgDaHYJlPMMo=", "dev": true, "license": "MIT", + "optional": true, "dependencies": { - "agent-base": "6", - "debug": "4" + "escape-string-regexp": "^4.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node": ">=10" } }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha1-oN10voHiqlwvJ+Zc4oNgXuTit/k=", "dev": true, "license": "MIT", "engines": { @@ -6016,8 +6376,8 @@ }, "node_modules/mime": { "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mime/-/mime-2.6.0.tgz", + "integrity": "sha1-oqaCqVzU0MsdYlfij4PafjWAA2c=", "dev": true, "license": "MIT", "bin": { @@ -6029,8 +6389,8 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha1-u6vNwChZ9JhzAchW4zh85exDv3A=", "dev": true, "license": "MIT", "engines": { @@ -6039,8 +6399,8 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha1-OBqHG2KnNEUGYK497uRIE/cNlZo=", "dev": true, "license": "MIT", "dependencies": { @@ -6050,20 +6410,10 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/mimic-response": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha1-SSNTiHju9CBjy4o+OweYeBSHqxs=", "dev": true, "license": "MIT", "engines": { @@ -6072,8 +6422,8 @@ }, "node_modules/minimatch": { "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha1-vUhoegvjjtKWE5kQVgD4MglYYdE=", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -6088,8 +6438,8 @@ }, "node_modules/minimist": { "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha1-waRk52kzAuCCoHXO4MBXdBrEdyw=", "dev": true, "license": "MIT", "funding": { @@ -6097,127 +6447,40 @@ } }, "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.7.tgz", - "integrity": "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA==", + "version": "7.1.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha1-eTibTrG7LQA6m7qH1JLyvTe9xls=", "dev": true, "license": "BlueOak-1.0.0", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.1.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha1-atdsOo8QInybUdHJrI4wsn9aJRw=", "dev": true, "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { - "node": ">= 8" + "node": ">= 18" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "0.5.6", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha1-fe8D0kMtyuS6HWEURcSDlgYiVfY=", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "minimist": "^1.2.6" + }, "bin": { "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/ms": { @@ -6245,33 +6508,30 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true, + "license": "MIT" }, "node_modules/node-abi": { - "version": "3.92.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.92.0.tgz", - "integrity": "sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ==", + "version": "4.33.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/node-abi/-/node-abi-4.33.0.tgz", + "integrity": "sha1-zOm3vODL+h1dWptpCLxe7WmJacw=", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.3.5" + "semver": "^7.6.3" }, "engines": { - "node": ">=10" + "node": ">=22.12.0" } }, "node_modules/node-abi/node_modules/semver": { "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-7.8.5.tgz", + "integrity": "sha1-ObZGA33VDBT7RR5+TKxY7YuGP2k=", "dev": true, "license": "ISC", "bin": { @@ -6281,18 +6541,10 @@ "node": ">=10" } }, - "node_modules/node-addon-api": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", - "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/node-api-version": { "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz", - "integrity": "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/node-api-version/-/node-api-version-0.2.1.tgz", + "integrity": "sha1-GbrVT21lYoy+5OYHoyXkSIrOLek=", "dev": true, "license": "MIT", "dependencies": { @@ -6301,8 +6553,8 @@ }, "node_modules/node-api-version/node_modules/semver": { "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-7.8.5.tgz", + "integrity": "sha1-ObZGA33VDBT7RR5+TKxY7YuGP2k=", "dev": true, "license": "ISC", "bin": { @@ -6313,45 +6565,54 @@ } }, "node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "version": "12.4.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/node-gyp/-/node-gyp-12.4.0.tgz", + "integrity": "sha1-LQF7bqHKkpTbvudb5TNyj0klcCQ=", "dev": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", + "nopt": "^9.0.0", + "proc-log": "^6.0.0", "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" + "tar": "^7.5.4", + "tinyglobby": "^0.2.12", + "undici": "^6.25.0", + "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^12.13 || ^14.13 || >=16" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/node-gyp/node_modules/env-paths": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha1-QgOZ1BbOH76bwKB8Yvpo1n/Q+PI=", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/node-gyp/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha1-SPZXavjoehj+t5a37V4uWQO0Pco=", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, "node_modules/node-gyp/node_modules/semver": { "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-7.8.5.tgz", + "integrity": "sha1-ObZGA33VDBT7RR5+TKxY7YuGP2k=", "dev": true, "license": "ISC", "bin": { @@ -6361,6 +6622,39 @@ "node": ">=10" } }, + "node_modules/node-gyp/node_modules/undici": { + "version": "6.27.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/undici/-/undici-6.27.0.tgz", + "integrity": "sha1-Qfnkj3xaQNJzdsqurYyan8e8qcQ=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "6.0.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/which/-/which-6.0.1.tgz", + "integrity": "sha1-AhZCRDoZj7k7eEpWBnIcsYz8v84=", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true, + "license": "MIT" + }, "node_modules/node-releases": { "version": "2.0.50", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.50.tgz", @@ -6372,36 +6666,25 @@ } }, "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "version": "9.0.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/nopt/-/nopt-9.0.0.tgz", + "integrity": "sha1-a/8INrKWTSRQi2tBtamknE9KH5Y=", "dev": true, "license": "ISC", "dependencies": { - "abbrev": "^1.0.0" + "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/normalize-url": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha1-QNCIW1Nd7/4/MUe+yHfQX+TFZoo=", "dev": true, "license": "MIT", "engines": { @@ -6411,21 +6694,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha1-HEfyct8nfzsdrwYWd9nILiMixg4=", "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, + "license": "MIT", + "optional": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">= 0.4" } }, "node_modules/obug": { @@ -6444,58 +6721,36 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha1-fqHBpdkddk+yghOciP4R4YKjpzQ=", "dev": true, "license": "MIT", "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, "node_modules/p-cancelable": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha1-qrf71BZYL6MqPbSYWcEiSHxe0s8=", "dev": true, "license": "MIT", "engines": { @@ -6504,8 +6759,8 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha1-4drMvnjQ0TiMoYxk/qOOPlfjcGs=", "dev": true, "license": "MIT", "dependencies": { @@ -6518,14 +6773,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha1-g8gxXGeFAF470CGDlBHJ4RDm2DQ=", "dev": true, "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" @@ -6534,65 +6789,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/package-json-from-dist": { + "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI=", "dev": true, "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha1-UTvb4tO5XXdi6METfvoZXGxhtbM=", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=0.10.0" } }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", - "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha1-WB9q3mWMu6ZaDTOA3ndTKVBU83U=", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=8" } }, "node_modules/pathe": { @@ -6604,8 +6841,8 @@ }, "node_modules/pe-library": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", - "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/pe-library/-/pe-library-0.4.1.tgz", + "integrity": "sha1-4mm+A0DcsTqmlJ10PafWWMPi++o=", "dev": true, "license": "MIT", "engines": { @@ -6637,14 +6874,45 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pkijs": { + "version": "3.4.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha1-2RZN7zD/bZe+LYiWbV42GSSZypw=", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@noble/hashes": "1.4.0", + "asn1js": "^3.0.6", + "bytestreamjs": "^2.0.1", + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/pkijs/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha1-RYFKoynzDk/guklCb0nfzN0GZCY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/plist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", - "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "version": "3.1.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/plist/-/plist-3.1.0.tgz", + "integrity": "sha1-eXpRapPmL1veVeC5zJyWf4YIk8k=", "dev": true, "license": "MIT", "dependencies": { - "@xmldom/xmldom": "^0.9.10", + "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" }, @@ -6681,13 +6949,68 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postject": { + "version": "1.0.0-alpha.6", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/postject/-/postject-1.0.0-alpha.6.tgz", + "integrity": "sha1-nQIjMicuLPzo3qTPzh7m3Rsu4TU=", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "commander": "^9.4.0" + }, + "bin": { + "postject": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/postject/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/commander/-/commander-9.5.0.tgz", + "integrity": "sha1-vAjR61zt98y3l6lhmdQce8PmDTA=", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha1-3rxkidem5rDnYRiIzsiAM30xY5Y=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretendard": { + "version": "1.3.9", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/pretendard/-/pretendard-1.3.9.tgz", + "integrity": "sha1-sfhtWnpyn1GJdAmPz4XzT/81Jrc=", + "license": "OFL-1.1" + }, + "node_modules/proc-log": { + "version": "6.1.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/proc-log/-/proc-log-6.1.0.tgz", + "integrity": "sha1-GFGUgqN9UZjiMRM6cBRKUPIfAhU=", + "dev": true, + "license": "ISC", + "engines": { + "node": "^20.17.0 || >=22.9.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha1-eCDZsWEgzFXKmud5JoCufbptf+I=", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/progress": { "version": "2.0.3", @@ -6699,17 +7022,10 @@ "node": ">=0.4.0" } }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, "node_modules/promise-retry": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha1-/3R6E2IKtXumiPX8Z4VUEMNw2iI=", "dev": true, "license": "MIT", "dependencies": { @@ -6720,10 +7036,22 @@ "node": ">=10" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha1-yLneKvay8WAQZ/mOAaxmuqIjFB8=", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/pump": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/pump/-/pump-3.0.4.tgz", + "integrity": "sha1-HzE0MFJ/qLkFYi69Iv4UROdXqzw=", "dev": true, "license": "MIT", "dependencies": { @@ -6733,18 +7061,38 @@ }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha1-AnQi4vrsCyXhVJw+G9gwm5EztuU=", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha1-7EbjTbdCK55P3FSQV4wYg2V9YAE=", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.5", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/pvutils/-/pvutils-1.1.5.tgz", + "integrity": "sha1-hLDepKXWcCSaqYAFEYBO4LfCgJw=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/quick-lru": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha1-NmST5rPkKjpoheLpnRj4D7eoyTI=", "dev": true, "license": "MIT", "engines": { @@ -6818,8 +7166,8 @@ }, "node_modules/read-binary-file-arch": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", - "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", + "integrity": "sha1-lZxGN9qpMigKm5EbGmdmp+RCiPw=", "dev": true, "license": "MIT", "dependencies": { @@ -6830,68 +7178,42 @@ } }, "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha1-kRJegEK7obmIf0k0X2J3Anzovps=", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "minimatch": "^5.1.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/readdir-glob/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, - "node_modules/readdir-glob/node_modules/brace-expansion": { + "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha1-iaf92TgmEmcxjq/hT5wy5ZjDaQk=", "dev": true, "license": "MIT", "engines": { @@ -6900,8 +7222,8 @@ }, "node_modules/resedit": { "version": "1.7.2", - "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", - "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/resedit/-/resedit-1.7.2.tgz", + "integrity": "sha1-sQQRcLmYEXEME/lJx9Ilhx3kzHg=", "dev": true, "license": "MIT", "dependencies": { @@ -6918,15 +7240,25 @@ }, "node_modules/resolve-alpn": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha1-t629rDVGqq7CC0Xn2CZZJwcnJvk=", "dev": true, "license": "MIT" }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/responselike": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha1-mgvI/cJS8/scymiwFlkQWboUIrw=", "dev": true, "license": "MIT", "dependencies": { @@ -6936,24 +7268,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/retry": { "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true, "license": "MIT", "engines": { @@ -6961,20 +7279,37 @@ } }, "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "2.6.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha1-stEE/g2Psnz54KHNqCYt04M8bKs=", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha1-9f55W3uDjM/jXcYI4Cgrnrouev0=", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8.0" } }, "node_modules/rolldown": { @@ -7083,17 +7418,10 @@ ], "license": "MIT" }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, "node_modules/sanitize-filename": { "version": "1.6.4", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.4.tgz", - "integrity": "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/sanitize-filename/-/sanitize-filename-1.6.4.tgz", + "integrity": "sha1-trOevtm9GhiYuFxcAwidp0WQ1vg=", "dev": true, "license": "WTFPL OR ISC", "dependencies": { @@ -7102,8 +7430,8 @@ }, "node_modules/sax": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", - "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/sax/-/sax-1.6.0.tgz", + "integrity": "sha1-2lljdikwe5fnxMso4ICnvDhWDVs=", "dev": true, "license": "BlueOak-1.0.0", "engines": { @@ -7129,17 +7457,35 @@ "semver": "bin/semver.js" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true, - "license": "ISC" + "license": "MIT", + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha1-8TYLBEf2H/tIPsQVfHN/q313jhg=", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha1-zNCvT4g1+9wmW4JGGq8MNmY/NOo=", "dev": true, "license": "MIT", "dependencies": { @@ -7151,8 +7497,8 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha1-rhbxZE2HPsrYQ7AwexQzYtTEIXI=", "dev": true, "license": "MIT", "engines": { @@ -7168,8 +7514,8 @@ }, "node_modules/signal-exit": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha1-qaF2f4r4QVURTqq9c/mSc8j1mtk=", "dev": true, "license": "ISC" }, @@ -7199,80 +7545,10 @@ "node": ">=10" } }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", - "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.1.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/socks-proxy-agent/node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -7291,8 +7567,8 @@ }, "node_modules/source-map-support": { "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha1-BP58f54e0tZiIzwoyys1ufY/bk8=", "dev": true, "license": "MIT", "dependencies": { @@ -7300,18 +7576,13 @@ "source-map": "^0.6.0" } }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha1-SRS5A6L4toXRf994pw6RfocuREo=", "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } + "license": "BSD-3-Clause", + "optional": true }, "node_modules/stackback": { "version": "0.0.2", @@ -7322,8 +7593,8 @@ }, "node_modules/stat-mode": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", - "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha1-aLVcth6mOf9XE282shaikYANFGU=", "dev": true, "license": "MIT", "engines": { @@ -7338,35 +7609,26 @@ "license": "MIT" }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "version": "1.1.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=", "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.2.0" + "safe-buffer": "~5.1.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=", "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, - "node_modules/string-width-cjs": { - "name": "string-width", + "node_modules/string-width": { "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha1-JpxxF9J7Ba0uU2gwqOyJXvnG0BA=", "dev": true, "license": "MIT", "dependencies": { @@ -7380,8 +7642,8 @@ }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha1-nibGPTD1NEPpSJSVshBdN7Z6hdk=", "dev": true, "license": "MIT", "dependencies": { @@ -7391,18 +7653,17 @@ "node": ">=8" } }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha1-MfEoGzgyYwQ0gxwxDAHMzajL4AY=", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/sumchecker": { @@ -7432,63 +7693,51 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "version": "7.5.20", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/tar/-/tar-7.5.20.tgz", + "integrity": "sha1-N6ZaqRHL1phkAC4Uv4qSalVR4kA=", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha1-AOLeRDY57Q14/YfeDSdGn7z/tTM=", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, + "license": "BlueOak-1.0.0", "engines": { - "node": ">=6" + "node": ">=18" } }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "node_modules/temp": { + "version": "0.9.4", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/temp/-/temp-0.9.4.tgz", + "integrity": "sha1-zSCoWAy2NjXQ5OnUvZidRChudiA=", "dev": true, - "license": "ISC", + "license": "MIT", + "peer": true, + "dependencies": { + "mkdirp": "^0.5.1", + "rimraf": "~2.6.2" + }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/temp-file": { "version": "3.4.0", - "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", - "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha1-dm6iiRHGg5lsJI7xog7qBNUWUsc=", "dev": true, "license": "MIT", "dependencies": { @@ -7496,6 +7745,26 @@ "fs-extra": "^10.0.0" } }, + "node_modules/tiny-async-pool": { + "version": "1.3.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz", + "integrity": "sha1-wBPhs2kJXnAF21WV+V5kbMpu+KU=", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.5.0" + } + }, + "node_modules/tiny-async-pool/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/semver/-/semver-5.7.2.tgz", + "integrity": "sha1-SNVdtzfDKHzUg14X+hP+rOHEHvg=", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/tinybench/-/tinybench-2.9.0.tgz", @@ -7542,8 +7811,8 @@ }, "node_modules/tmp": { "version": "0.2.7", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", - "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha1-JvTbEdFgHOgBLcuKeY7OHAapkFk=", "dev": true, "license": "MIT", "engines": { @@ -7552,8 +7821,8 @@ }, "node_modules/tmp-promise": { "version": "3.0.3", - "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha1-YKGhzJjJiGdPy/0jtuM2e96sTOc=", "dev": true, "license": "MIT", "dependencies": { @@ -7562,21 +7831,60 @@ }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", "dev": true, "license": "WTFPL", "dependencies": { "utf8-byte-length": "^1.0.1" } }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha1-Ss1KFV4ic0mQpe0f6el/ETvLN8E=", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/tslib/-/tslib-2.8.1.tgz", "integrity": "sha1-YS7+TtI11Wfoq6Xypfq3AoCt6D8=", "dev": true, - "license": "0BSD", - "optional": true + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha1-B7ggO/pwVsBlcFDjzNLDdzC6uPE=", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha1-AXLLW86AsL1ULqNI21DH4hg02TQ=", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/typescript": { "version": "5.9.3", @@ -7592,6 +7900,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.64.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/typescript-eslint/-/typescript-eslint-8.64.0.tgz", + "integrity": "sha1-SYTa5N6dyL+JKs9cOU0KKl8Iw+E=", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.64.0", + "@typescript-eslint/parser": "8.64.0", + "@typescript-eslint/typescript-estree": "8.64.0", + "@typescript-eslint/utils": "8.64.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, "node_modules/undici": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", @@ -7610,40 +7942,43 @@ "dev": true, "license": "MIT" }, - "node_modules/unique-filename": { + "node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha1-Fo78IYCWTmOG0GHglN9hr+I5sY0=", "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">= 10.0.0" } }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "node_modules/unzipper": { + "version": "0.12.5", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/unzipper/-/unzipper-0.12.5.tgz", + "integrity": "sha1-f8a0hi84MiAtH1zDrb7iZ53qr2w=", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "bluebird": "~3.7.2", + "duplexer2": "~0.1.4", + "fs-extra": "11.3.1", + "graceful-fs": "^4.2.2", + "node-int64": "^0.4.0" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/unzipper/node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha1-unofl6hflMbbLlL/aVcNs2cdWnQ=", "dev": true, "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=14.14" } }, "node_modules/update-browserslist-db": { @@ -7679,8 +8014,8 @@ }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha1-mxpSWVIlhZ5V9mnZKPiMbFfyp34=", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -7698,34 +8033,18 @@ }, "node_modules/utf8-byte-length": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha1-+fY5ENFVNu4rLV3UZlOJcV6sXB4=", "dev": true, "license": "(WTFPL OR MIT)" }, "node_modules/util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "license": "MIT" }, - "node_modules/verror": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", - "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/vite": { "version": "5.4.21", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", @@ -8448,30 +8767,34 @@ "node": ">=0.10.0" } }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "node_modules/webcrypto-core": { + "version": "1.9.2", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/webcrypto-core/-/webcrypto-core-1.9.2.tgz", + "integrity": "sha1-It1qD7VSF7EwHqtxUdAdXGjlLMs=", "dev": true, "license": "MIT", "dependencies": { - "defaults": "^1.0.3" + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/json-schema": "^1.1.12", + "@peculiar/utils": "^2.0.2", + "asn1js": "^3.0.10", + "tslib": "^2.8.1" } }, "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "version": "5.0.0", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/which/-/which-5.0.0.tgz", + "integrity": "sha1-2T8tk/eYNNQ2PH0MI+ANB8RmyNY=", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { - "node-which": "bin/node-which" + "node-which": "bin/which.js" }, "engines": { - "node": ">= 8" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/why-is-node-running": { @@ -8491,39 +8814,20 @@ "node": ">=8" } }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha1-0sRcbdT7zmIaZvE2y+Mor9BBCzQ=", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", + "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha1-Z+FFz/UQpqaYS98RUpEdadLrnkM=", "dev": true, "license": "MIT", "dependencies": { @@ -8540,15 +8844,15 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "license": "ISC" }, "node_modules/xmlbuilder": { "version": "15.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "resolved": "https://ms-feed-25.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha1-nc3OSe6mbY0QtCyulKecPI0MLsU=", "dev": true, "license": "MIT", "engines": { @@ -8557,8 +8861,8 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "resolved": "https://ms-feed-12.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha1-f0k00PfKjFb5UxSTndzS3ZHOHVU=", "dev": true, "license": "ISC", "engines": { @@ -8574,8 +8878,8 @@ }, "node_modules/yargs": { "version": "17.7.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", - "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha1-d53/5ryv7FlqcXLpgyiaWIZH+qo=", "dev": true, "license": "MIT", "dependencies": { @@ -8593,8 +8897,8 @@ }, "node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha1-kJa87r+ZDSG7MfqVFuDt4pSnfTU=", "dev": true, "license": "ISC", "engines": { @@ -8603,8 +8907,8 @@ }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "resolved": "https://ms-feed-2.pkgs.visualstudio.com/1es-public/_packaging/npm-public/npm/registry/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha1-ApTrPe4FAo0x7hpfosVWpqrxChs=", "dev": true, "license": "MIT", "engines": { @@ -8613,45 +8917,6 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } - }, - "node_modules/zip-stream": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", - "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "archiver-utils": "^3.0.4", - "compress-commons": "^4.1.2", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/zip-stream/node_modules/archiver-utils": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", - "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "glob": "^7.2.3", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } } } } diff --git a/package.json b/package.json index 6ab6b0d..8e53bda 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,9 @@ "main": "./out/main/index.js", "author": "CopilotWatchTower", "license": "MIT", + "engines": { + "node": ">=22.5.0" + }, "scripts": { "dev": "electron-vite dev", "build": "electron-vite build", @@ -13,6 +16,8 @@ "test:watch": "vitest", "test:coverage": "vitest run --coverage", "typecheck": "tsc --noEmit -p tsconfig.json", + "lint": "eslint .", + "lint:fix": "eslint . --fix", "dist": "electron-vite build && electron-builder --win portable" }, "dependencies": { @@ -21,20 +26,26 @@ "i18next": "^26.3.3", "koffi": "^3.0.2", "lucide-react": "^0.460.0", + "pretendard": "^1.3.9", "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^17.0.8" }, "devDependencies": { + "@eslint/js": "^9.39.5", "@types/node": "^22.9.0", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.3", "@vitest/coverage-v8": "^4.1.10", "electron": "^42.5.0", - "electron-builder": "^25.1.8", + "electron-builder": "^26.15.3", "electron-vite": "^2.3.0", + "eslint": "^9.39.5", + "eslint-plugin-react-hooks": "^5.2.0", + "globals": "^15.15.0", "typescript": "^5.6.3", + "typescript-eslint": "^8.64.0", "vite": "^5.4.11", "vitest": "^4.1.10" } diff --git a/src/main/collectors/consumption.ts b/src/main/collectors/consumption.ts index 4d968a4..c68227c 100644 --- a/src/main/collectors/consumption.ts +++ b/src/main/collectors/consumption.ts @@ -5,6 +5,7 @@ * point-in-time snapshots into power_platform_consumption. */ import { upsertConsumptionRows, type ConsumptionRow } from '../db' +import { httpRequest } from '../http' const LICENSING_HOST = 'https://licensing.powerplatform.microsoft.com' @@ -43,14 +44,20 @@ function datePart(value: unknown): string | null { async function getJson(token: string, path: string, params?: Record): Promise { const url = new URL(LICENSING_HOST + path) if (params) for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v) - const res = await fetch(url, { + const res = await httpRequest(url.toString(), { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' } }) if (!res.ok) { - const body = await res.text() + const body = await res.text().catch(() => '') throw new Error(`Licensing ${res.status} ${path} :: ${body.slice(0, 160)}`) } - return res.json() + const text = await res.text() + if (!text.trim()) return null + try { + return JSON.parse(text) + } catch { + throw new Error(`Licensing ${path} :: expected JSON, got ${text.slice(0, 160)}`) + } } function parseCurrencyReports(data: unknown, snapshotDate: string): ConsumptionRow[] { diff --git a/src/main/collectors/dataverse.ts b/src/main/collectors/dataverse.ts index 9e55b28..cd47384 100644 --- a/src/main/collectors/dataverse.ts +++ b/src/main/collectors/dataverse.ts @@ -9,6 +9,7 @@ import * as db from '../db' import { recomputeThreads } from '../threading' import { analyzeAgent, parentBotId } from './agentRisk' import type { PortalTokens } from '../portal' +import { httpRequest } from '../http' const DISCOVERY_INSTANCES_URL = 'https://globaldisco.crm.dynamics.com/api/discovery/v2.0/Instances' const DISCOVERY_HOST = 'globaldisco.crm.dynamics.com' @@ -207,7 +208,7 @@ export function parseEnvironmentsJson(data: unknown): DataverseEnvironment[] { // ---- HTTP client ------------------------------------------------------- async function getJson(url: string, token: string, prefer = 'odata.maxpagesize=200'): Promise { - const res = await fetch(url, { + const res = await httpRequest(url, { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json', @@ -217,10 +218,16 @@ async function getJson(url: string, token: string, prefer = 'odata.maxpagesize=2 } }) if (!res.ok) { - const body = await res.text() + const body = await res.text().catch(() => '') throw new Error(`Dataverse ${res.status} ${url.slice(0, 80)} :: ${body.slice(0, 160)}`) } - return (await res.json()) as Dict + const text = await res.text() + if (!text.trim()) return {} as Dict + try { + return JSON.parse(text) as Dict + } catch { + throw new Error(`Dataverse ${url.slice(0, 80)} :: expected JSON, got ${text.slice(0, 160)}`) + } } async function discoverEnvironments(token: string): Promise { @@ -251,7 +258,25 @@ async function resolveEnvironments( return orgHosts.map((host) => ({ id: host, url: `https://${host}`, friendlyName: host })) } -async function fetchTranscripts(env: DataverseEnvironment, token: string, maxPages = 50): Promise { +type OnLog = (line: string) => void + +/** + * Paging stops at `maxPages` to bound a runaway collection. Truncation used to + * be silent, so a partial dataset was indistinguishable from a complete one — + * unacceptable for a governance report. Always say so out loud. + */ +function warnTruncated(onLog: OnLog | undefined, label: string, pages: number, rows: number): void { + onLog?.( + `⚠ ${label}: ${pages} 페이지(${rows} 행)에서 중단했습니다 — 결과가 잘렸을 수 있습니다. 기간/필터를 좁혀 다시 수집하세요.` + ) +} + +async function fetchTranscripts( + env: DataverseEnvironment, + token: string, + onLog?: OnLog, + maxPages = 50 +): Promise { const base = env.url.replace(/\/+$/, '') let url: string | null = `${base}/api/data/${API_VERSION}/conversationtranscripts?$select=conversationtranscriptid,content,createdon,name,schematype,_botid_value` @@ -263,6 +288,7 @@ async function fetchTranscripts(env: DataverseEnvironment, token: string, maxPag url = (data['@odata.nextLink'] as string) ?? null pages++ } + if (url) warnTruncated(onLog, `${env.friendlyName || env.id} conversationtranscripts`, pages, out.length) return out } @@ -316,7 +342,7 @@ export async function collectTranscripts( continue } try { - const transcripts = await fetchTranscripts(env, token) + const transcripts = await fetchTranscripts(env, token, onLog) result.transcripts += transcripts.length const bots = await fetchBots(env, token) const interactions: db.InteractionUpsert[] = [] @@ -416,7 +442,12 @@ export function parseFlowRunRecord(record: Dict, environmentId: string | null, e } } -async function fetchFlowRuns(env: DataverseEnvironment, token: string, maxPages = 50): Promise { +async function fetchFlowRuns( + env: DataverseEnvironment, + token: string, + onLog?: OnLog, + maxPages = 50 +): Promise { const base = env.url.replace(/\/+$/, '') let url: string | null = `${base}/api/data/${API_VERSION}/flowruns?$select=${FLOW_RUN_SELECT}&$orderby=createdon desc` const out: Dict[] = [] @@ -427,6 +458,7 @@ async function fetchFlowRuns(env: DataverseEnvironment, token: string, maxPages url = (data['@odata.nextLink'] as string) ?? null pages++ } + if (url) warnTruncated(onLog, `${env.friendlyName || env.id} flowruns`, pages, out.length) return out } @@ -453,7 +485,7 @@ export async function collectFlowRuns(tokens: PortalTokens, onLog?: (line: strin continue } try { - const records = await fetchFlowRuns(env, token) + const records = await fetchFlowRuns(env, token, onLog) const rows = records .map((r) => parseFlowRunRecord(r, env.id, env.friendlyName)) .filter((r): r is db.FlowRunRow => r !== null) @@ -479,7 +511,7 @@ async function fetchEntity( env: DataverseEnvironment, token: string, entitySet: string, - opts: { select?: string; top?: number; includeFormatted?: boolean; maxPages?: number } + opts: { select?: string; top?: number; includeFormatted?: boolean; maxPages?: number; onLog?: OnLog } ): Promise { const base = env.url.replace(/\/+$/, '') const params = new URLSearchParams() @@ -499,6 +531,7 @@ async function fetchEntity( url = (data['@odata.nextLink'] as string) ?? null pages++ } + if (url) warnTruncated(opts.onLog, `${env.friendlyName || env.id} ${entitySet}`, pages, out.length) return out } @@ -534,7 +567,12 @@ export async function collectAgentDefinitions(tokens: PortalTokens, onLog?: (lin continue } try { - const bots = await fetchEntity(env, token, 'bots', { select: BOT_SELECT, includeFormatted: true, maxPages: 20 }) + const bots = await fetchEntity(env, token, 'bots', { + select: BOT_SELECT, + includeFormatted: true, + maxPages: 20, + onLog + }) if (!bots.length) { onLog?.(`${label}: 에이전트 없음`) continue @@ -542,7 +580,8 @@ export async function collectAgentDefinitions(tokens: PortalTokens, onLog?: (lin const components = await fetchEntity(env, token, 'botcomponents', { select: BOTCOMPONENT_SELECT, top: 5000, - maxPages: 50 + maxPages: 50, + onLog }) const byBot = new Map() for (const c of components) { diff --git a/src/main/collectors/ediscovery.ts b/src/main/collectors/ediscovery.ts index 85be527..4794dbb 100644 --- a/src/main/collectors/ediscovery.ts +++ b/src/main/collectors/ediscovery.ts @@ -24,6 +24,7 @@ import { PublicClientApplication, type AccountInfo } from '@azure/msal-node' import * as db from '../db' import { makeCachePlugin } from '../tokenCache' import { parseExportPackage } from './ediscoveryExport' +import { httpRequest, DOWNLOAD_TIMEOUT_MS, type HttpOptions } from '../http' const GRAPH_V1 = 'https://graph.microsoft.com/v1.0' // Well-known Microsoft Graph PowerShell public client (multi-tenant, device-code). @@ -119,12 +120,25 @@ async function delegatedToken(tenantId: string, cacheDir: string, onCode: OnDevi // ---- Graph request helpers ---------------------------------------------- type Json = Record -async function gReq(token: string, method: string, url: string, body?: unknown): Promise { - const res = await fetch(url, { - method, - headers: { Authorization: `Bearer ${token}`, ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}) }, - body: body !== undefined ? JSON.stringify(body) : undefined - }) +async function gReq( + token: string, + method: string, + url: string, + body?: unknown, + opts: HttpOptions = {} +): Promise { + const res = await httpRequest( + url, + { + method, + headers: { + Authorization: `Bearer ${token}`, + ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}) + }, + body: body !== undefined ? JSON.stringify(body) : undefined + }, + opts + ) if (!res.ok) { const text = await res.text().catch(() => '') if (res.status === 403) @@ -136,9 +150,28 @@ async function gReq(token: string, method: string, url: string, body?: unknown): return res } -async function gJson(token: string, method: string, url: string, body?: unknown): Promise { - const res = await gReq(token, method, url, body) - return (await res.json().catch(() => ({}))) as Json +/** + * A response body that is not valid JSON is an error, never `{}`. Swallowing + * it here used to turn an HTML error page into "0 cases found", which silently + * produced duplicate cases and empty collections. + */ +async function gJson( + token: string, + method: string, + url: string, + body?: unknown, + opts: HttpOptions = {} +): Promise { + const res = await gReq(token, method, url, body, opts) + const text = await res.text() + if (!text.trim()) return {} + try { + return JSON.parse(text) as Json + } catch { + throw new EdiscoveryError( + `Graph ${method} ${url.slice(0, 80)}: JSON 응답을 기대했지만 다른 형식을 받았습니다: ${text.slice(0, 200)}` + ) + } } async function gPaginate(token: string, url: string): Promise { @@ -314,11 +347,6 @@ function extractDownloadUrl(payload: Json): [string | null, boolean] { function nowIso(): string { return new Date().toISOString().replace(/\.\d+Z$/, 'Z') } -function runStamp(job: db.EdiscoveryJob): string { - const digits = (job.createdAt || '').split('+')[0].replace(/[^0-9]/g, '') - if (digits.length >= 14) return `${digits.slice(0, 8)}-${digits.slice(8, 14)}` - return (job.id || 'job').slice(0, 12) -} function caseDisplayName(job: db.EdiscoveryJob): string { const alias = (job.targetUpn || 'all').split('@')[0] || 'all' // Stable per-user name so the case is REUSED instead of piling up one per run. @@ -352,6 +380,13 @@ async function pollOperation( } } +/** + * Node cannot allocate a Buffer larger than ~2 GiB, and the ZIP parser needs the + * whole package resident. Refuse oversized packages with an actionable message + * instead of dying with an out-of-memory crash mid-collection. + */ +const MAX_EXPORT_BYTES = 1_500_000_000 + async function downloadAndParse( job: db.EdiscoveryJob, onProgress: OnProgress, @@ -371,10 +406,21 @@ async function downloadAndParse( } else { // ME5 / eDiscovery Premium: Azure Blob SAS — direct programmatic download. onProgress('downloading', '내보내기 패키지를 다운로드하는 중…') - const res = await fetch(job.exportUrl) + const res = await httpRequest(job.exportUrl, {}, { timeoutMs: DOWNLOAD_TIMEOUT_MS }) if (!res.ok) throw new EdiscoveryError(`다운로드 실패 ${res.status}`) + const declared = Number(res.headers.get('content-length') ?? '0') + if (declared > MAX_EXPORT_BYTES) { + throw new EdiscoveryError( + `내보내기 패키지가 너무 큽니다(${Math.round(declared / 1e9)} GB). 기간을 좁혀 다시 수집하세요.` + ) + } buf = Buffer.from(await res.arrayBuffer()) } + if (buf.length > MAX_EXPORT_BYTES) { + throw new EdiscoveryError( + `내보내기 패키지가 너무 큽니다(${Math.round(buf.length / 1e9)} GB). 기간을 좁혀 다시 수집하세요.` + ) + } onProgress('parsing', `패키지 파싱 중… (${Math.round(buf.length / 1024)} KB)`) const userId = job.targetUserId || `ediscovery:${job.targetUpn.toLowerCase()}` return parseExportPackage(buf, userId, (line) => onProgress('parsing', line)) diff --git a/src/main/collectors/ediscoveryExport.ts b/src/main/collectors/ediscoveryExport.ts index d2a22f9..2f6f809 100644 --- a/src/main/collectors/ediscoveryExport.ts +++ b/src/main/collectors/ediscoveryExport.ts @@ -43,8 +43,14 @@ interface ParsedItem { function isoNow(): string { return new Date().toISOString() } -function iso(value: unknown): string { - if (value === null || value === undefined || value === '') return isoNow() +/** + * Parse an export timestamp. Returns null when the value is absent or + * unparseable so the caller can flag it: substituting "now" silently made an + * undated item look like the most recent activity in the tenant, which is + * exactly the kind of fabricated evidence a governance tool must never emit. + */ +function iso(value: unknown): string | null { + if (value === null || value === undefined || value === '') return null const text = String(value).trim() // Teams/Copilot timestamps are epoch milliseconds (e.g. creationDate // 1782027647001). Date(string) can't parse those, so convert explicitly. @@ -60,6 +66,9 @@ function iso(value: unknown): string { return d.toISOString() } +/** Marker written into `raw` when `createdAt` had to be synthesised. */ +export const CREATED_AT_UNKNOWN = '__createdAtUnknown' + /** Split a combined Copilot body into ordered (type, text) turns. */ export function splitCopilotBody(body: string): Array<[string, string]> { if (!body || !body.trim()) return [] @@ -109,7 +118,8 @@ function turnsFromPairs(itemId: string, pairs: Array<[string, string]>, createdA function parseNormalisedRecord(rec: Dict, fallbackId: string): ParsedItem { const itemId = String(rec.id ?? rec.itemId ?? fallbackId) const conversationId = rec.conversationId ?? rec.conversation_id ?? rec.threadId - const createdAt = iso(rec.createdDateTime ?? rec.created_at ?? rec.date) + const parsedAt = iso(rec.createdDateTime ?? rec.created_at ?? rec.date) + const createdAt = parsedAt ?? isoNow() const app = (rec.app ?? rec.appHost ?? DEFAULT_APP) as string const pairs: Array<[string, string]> = [] if (rec.prompt) pairs.push([USER_PROMPT, String(rec.prompt)]) @@ -121,7 +131,7 @@ function parseNormalisedRecord(rec: Dict, fallbackId: string): ParsedItem { createdAt, app: app ? String(app) : DEFAULT_APP, turns: turnsFromPairs(itemId, finalPairs, createdAt), - raw: rec + raw: parsedAt ? rec : { ...rec, [CREATED_AT_UNKNOWN]: true } } } @@ -146,7 +156,8 @@ function parseEmlBytes(data: Buffer, name: string): ParsedItem | null { const subject = headers.get('subject') ?? '' const messageId = (headers.get('message-id') ?? name).replace(/[<>]/g, '') || name const conversationId = headers.get('thread-index') ?? headers.get('x-conversation-id') ?? messageId - const createdAt = iso(headers.get('date')) + const parsedAt = iso(headers.get('date')) ?? iso(headers.get('received')?.split(';').pop()?.trim()) + const createdAt = parsedAt ?? isoNow() let pairs = body ? splitCopilotBody(body) : [] if (subject && (!pairs.length || pairs[0][0] !== USER_PROMPT)) { pairs = [[USER_PROMPT, subject], ...pairs] @@ -157,7 +168,7 @@ function parseEmlBytes(data: Buffer, name: string): ParsedItem | null { createdAt, app: DEFAULT_APP, turns: turnsFromPairs(messageId, pairs, createdAt), - raw: { subject, name } + raw: parsedAt ? { subject, name } : { subject, name, [CREATED_AT_UNKNOWN]: true } } } @@ -169,13 +180,16 @@ function msgStream(container: CfbContainer, name: string): Buffer | null { if (!e || !e.content) return null return Buffer.from(e.content as Uint8Array) } +/** MSG properties are UTF-16 blobs; NUL padding is data, not text. */ function cleanMsgText(value: string): string { + // eslint-disable-next-line no-control-regex -- NUL is meaningful binary padding here return value.replace(/\u0000/g, '').replace(/[ \t\r\f\v]+/g, ' ').trim() } /** Parse a Teams/Copilot ItemData JSON blob (a `{SchemaVersion,ItemData}` * wrapper, or the item object directly). */ function parseItemDataText(text: string): Dict | null { try { + // eslint-disable-next-line no-control-regex -- NUL is meaningful binary padding here const outer = JSON.parse(text.replace(/\u0000/g, '').trim()) as Dict let parsed: unknown = outer.ItemData if (typeof parsed === 'string') parsed = JSON.parse(parsed) @@ -412,7 +426,8 @@ function parseMsgBytes(data: Buffer, name: string): ParsedItem | null { itemData.originalarrivaltime ?? itemData.composetime ?? itemData.createdDateTime - const createdAt = iso(ts ?? (msgDate(container) || undefined)) + const parsedAt = iso(ts ?? (msgDate(container) || undefined)) + const createdAt = parsedAt ?? isoNow() const body = unwrapSwiftCard( cleanMsgText(String(itemData.content ?? '')) || uni('1000001F') || htmlBodyText(container) ) @@ -426,11 +441,12 @@ function parseMsgBytes(data: Buffer, name: string): ParsedItem | null { createdAt, app: DEFAULT_APP, turns, - raw: { subject, name, messageId, itemData } + raw: parsedAt ? { subject, name, messageId, itemData } : { subject, name, messageId, itemData, [CREATED_AT_UNKNOWN]: true } } } // Non-Teams item: split the plain body on User:/Copilot: markers. - const createdAt = iso(msgDate(container) || undefined) + const parsedAt = iso(msgDate(container) || undefined) + const createdAt = parsedAt ?? isoNow() const body = unwrapSwiftCard(uni('1000001F') || htmlBodyText(container)) // PidTagBody, HTML, then SWIFT card let pairs = body ? splitCopilotBody(body) : [] if (subject && (!pairs.length || pairs[0][0] !== USER_PROMPT)) pairs = [[USER_PROMPT, subject], ...pairs] @@ -448,41 +464,159 @@ function parseMsgBytes(data: Buffer, name: string): ParsedItem | null { createdAt, app: DEFAULT_APP, turns: turnsFromPairs(messageId, pairs, createdAt), - raw: { subject, name } + raw: parsedAt ? { subject, name } : { subject, name, [CREATED_AT_UNKNOWN]: true } } } -/** Minimal dependency-free ZIP reader (central directory + raw inflate). */ -export function readZipEntries(buf: Buffer): Array<{ name: string; data: Buffer }> { +const EOCD_SIG = 0x06054b50 +const EOCD64_LOCATOR_SIG = 0x07064b50 +const EOCD64_SIG = 0x06064b50 +const CD_ENTRY_SIG = 0x02014b50 +const U32_MAX = 0xffffffff +const U16_MAX = 0xffff +/** ZIP comment is at most 64 KiB, so the EOCD can never be further back than this. */ +const MAX_EOCD_SEARCH = 0xffff + 22 + +/** Read a ZIP64 8-byte value, refusing offsets a Buffer index cannot represent. */ +function u64(buf: Buffer, at: number): number { + const v = buf.readBigUInt64LE(at) + if (v > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error(`ZIP64 값이 너무 큽니다: ${v}`) + return Number(v) +} + +/** + * ZIP64 stores the real sizes/offsets in a 0x0001 extra field whenever the + * classic 32-bit slot is saturated (0xffffffff). Fields appear in a fixed order + * but only the saturated ones are present, so they must be consumed in order. + */ +function zip64Extra( + extra: Buffer, + need: { uncompSize: boolean; compSize: boolean; localHeaderOffset: boolean } +): { compSize?: number; localHeaderOffset?: number } { + let at = 0 + while (at + 4 <= extra.length) { + const id = extra.readUInt16LE(at) + const size = extra.readUInt16LE(at + 2) + const dataAt = at + 4 + if (dataAt + size > extra.length) break + if (id === 0x0001) { + const field = extra.subarray(dataAt, dataAt + size) + let cursor = 0 + const take = (): number | undefined => { + if (cursor + 8 > field.length) return undefined + const v = u64(field, cursor) + cursor += 8 + return v + } + if (need.uncompSize) take() + const compSize = need.compSize ? take() : undefined + const localHeaderOffset = need.localHeaderOffset ? take() : undefined + return { compSize, localHeaderOffset } + } + at = dataAt + size + } + return {} +} + +/** + * Minimal dependency-free ZIP reader (central directory + raw inflate) with + * ZIP64 support. eDiscovery export packages routinely exceed 4 GB or 65 535 + * entries; without ZIP64 the classic EOCD reports 0xffff/0xffffffff sentinels + * and the reader silently returned an empty or truncated entry list — i.e. a + * "0 interactions" collection that looked successful. + * + * @param onWarn receives per-entry problems. A single corrupt entry must not + * abort the package, but it must never be silently swallowed either. + */ +export function readZipEntries( + buf: Buffer, + onWarn?: (line: string) => void +): Array<{ name: string; data: Buffer }> { const out: Array<{ name: string; data: Buffer }> = [] let eocd = -1 - for (let i = buf.length - 22; i >= 0; i--) { - if (buf.readUInt32LE(i) === 0x06054b50) { + const floor = Math.max(0, buf.length - MAX_EOCD_SEARCH) + for (let i = buf.length - 22; i >= floor; i--) { + if (buf.readUInt32LE(i) === EOCD_SIG) { eocd = i break } } - if (eocd < 0) return out - const count = buf.readUInt16LE(eocd + 10) + if (eocd < 0) { + onWarn?.('ZIP 중앙 디렉터리(EOCD)를 찾지 못했습니다 — 손상되었거나 ZIP이 아닙니다.') + return out + } + + let count = buf.readUInt16LE(eocd + 10) let cd = buf.readUInt32LE(eocd + 16) + + // ZIP64: the locator sits immediately before the classic EOCD. + const locator = eocd - 20 + if (locator >= 0 && buf.readUInt32LE(locator) === EOCD64_LOCATOR_SIG) { + try { + const eocd64 = u64(buf, locator + 8) + if (eocd64 >= 0 && eocd64 + 56 <= buf.length && buf.readUInt32LE(eocd64) === EOCD64_SIG) { + count = u64(buf, eocd64 + 32) + cd = u64(buf, eocd64 + 48) + } + } catch (e) { + onWarn?.(`ZIP64 헤더를 읽지 못했습니다: ${e instanceof Error ? e.message : String(e)}`) + } + } else if (count === U16_MAX || cd === U32_MAX) { + onWarn?.('ZIP64 형식으로 보이지만 ZIP64 로케이터가 없습니다 — 일부 항목이 누락될 수 있습니다.') + } + for (let n = 0; n < count; n++) { - if (cd + 46 > buf.length || buf.readUInt32LE(cd) !== 0x02014b50) break + if (cd + 46 > buf.length || buf.readUInt32LE(cd) !== CD_ENTRY_SIG) { + if (n < count) onWarn?.(`중앙 디렉터리가 ${n}/${count} 항목에서 끊겼습니다.`) + break + } const method = buf.readUInt16LE(cd + 10) - const compSize = buf.readUInt32LE(cd + 20) + let compSize = buf.readUInt32LE(cd + 20) + const uncompSize = buf.readUInt32LE(cd + 24) const nameLen = buf.readUInt16LE(cd + 28) const extraLen = buf.readUInt16LE(cd + 30) const commentLen = buf.readUInt16LE(cd + 32) - const lho = buf.readUInt32LE(cd + 42) + let lho = buf.readUInt32LE(cd + 42) const name = buf.toString('utf8', cd + 46, cd + 46 + nameLen) + + if (compSize === U32_MAX || lho === U32_MAX || uncompSize === U32_MAX) { + try { + const extra = buf.subarray(cd + 46 + nameLen, cd + 46 + nameLen + extraLen) + const z = zip64Extra(extra, { + uncompSize: uncompSize === U32_MAX, + compSize: compSize === U32_MAX, + localHeaderOffset: lho === U32_MAX + }) + if (z.compSize !== undefined) compSize = z.compSize + if (z.localHeaderOffset !== undefined) lho = z.localHeaderOffset + } catch (e) { + onWarn?.(`${name}: ZIP64 확장 필드 해석 실패 — 건너뜁니다 (${e instanceof Error ? e.message : String(e)})`) + cd += 46 + nameLen + extraLen + commentLen + continue + } + } + + if (lho + 30 > buf.length) { + onWarn?.(`${name}: 로컬 헤더 오프셋이 패키지 범위를 벗어났습니다 — 건너뜁니다.`) + cd += 46 + nameLen + extraLen + commentLen + continue + } const lfnLen = buf.readUInt16LE(lho + 26) const lefLen = buf.readUInt16LE(lho + 28) const dataStart = lho + 30 + lfnLen + lefLen + if (dataStart + compSize > buf.length) { + onWarn?.(`${name}: 압축 데이터가 패키지 범위를 벗어났습니다 — 건너뜁니다.`) + cd += 46 + nameLen + extraLen + commentLen + continue + } const comp = buf.subarray(dataStart, dataStart + compSize) let data: Buffer try { data = method === 0 ? Buffer.from(comp) : inflateRawSync(comp) - } catch { - data = Buffer.alloc(0) + } catch (e) { + onWarn?.(`${name}: 압축 해제 실패 — 이 항목은 수집되지 않습니다 (${e instanceof Error ? e.message : String(e)})`) + cd += 46 + nameLen + extraLen + commentLen + continue } out.push({ name, data }) cd += 46 + nameLen + extraLen + commentLen @@ -541,13 +675,18 @@ export function parseExportEntries( else msgDropped++ } else if (lower.endsWith('.zip')) { // Nested export package (some tenants wrap items in per-source zips). - items.push(...parseExportEntries(readZipEntries(entry.data), onLog)) + items.push(...parseExportEntries(readZipEntries(entry.data, onLog), onLog)) } } catch (e) { onLog?.(`항목 파싱 실패 ${entry.name}: ${e instanceof Error ? e.message : String(e)}`) } } if (msgDropped) onLog?.(`본문 없는 .msg ${msgDropped}개 건너뜀`) + const undated = items.filter((i) => i.raw[CREATED_AT_UNKNOWN]).length + if (undated) + onLog?.( + `⚠ 타임스탬프가 없는 항목 ${undated}개 — 수집 시각으로 대체했습니다. 이 항목의 시간 기반 분석은 신뢰할 수 없습니다.` + ) return items } @@ -557,7 +696,7 @@ export function parseExportPackage( targetUserId: string, onLog?: (line: string) => void ): InteractionUpsert[] { - const items = parseExportEntries(readZipEntries(zipBytes), onLog) + const items = parseExportEntries(readZipEntries(zipBytes, onLog), onLog) const rows: InteractionUpsert[] = [] for (const item of items) { item.turns.forEach((turn, idx) => { diff --git a/src/main/csv.ts b/src/main/csv.ts new file mode 100644 index 0000000..ba29d57 --- /dev/null +++ b/src/main/csv.ts @@ -0,0 +1,17 @@ +/** + * CSV serialisation for table exports (RFC 4180 quoting, CRLF line endings). + * Extracted so both the `export_table` IPC handler and the dev harness share + * one implementation that can be unit-tested without booting Electron. + */ +export function toCsv(rows: Record[]): string { + if (!rows.length) return '' + const headers = Object.keys(rows[0]) + const esc = (v: unknown): string => { + if (v === null || v === undefined) return '' + const s = String(v) + return /[",\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s + } + const lines = [headers.join(',')] + for (const r of rows) lines.push(headers.map((h) => esc(r[h])).join(',')) + return lines.join('\r\n') +} diff --git a/src/main/db.ts b/src/main/db.ts index a28cc4d..fcf2d0b 100644 --- a/src/main/db.ts +++ b/src/main/db.ts @@ -1,10 +1,11 @@ /** - * Read-only data access over the Python app's per-profile SQLite store. + * Read/write data access over the per-profile SQLite store shared with the + * legacy Python app. * * Uses Electron's built-in `node:sqlite` (Node 22+/Electron 42) so there is * NO native module to compile or ship — important for portable builds. * Resolves the active profile from %LOCALAPPDATA%/CopilotWatchTower/profiles.json - * and opens profiles//store.db read-only. + * and opens profiles//store.db. */ import { DatabaseSync } from 'node:sqlite' import { existsSync, readFileSync } from 'node:fs' @@ -76,23 +77,51 @@ function ensureRuntimeSchema(database: DatabaseSync): void { ) } +let lastOpenError: string | null = null + +/** Diagnostic for the last failed openDb() — surfaced to the UI instead of a bare "no data". */ +export function lastDbError(): string | null { + return lastOpenError +} + export function openDb(): boolean { if (db) return true const path = resolveDbPath() - if (!path) return false + if (!path) { + lastOpenError = 'no-profile-db' + return false + } try { db = new DatabaseSync(path, { readOnly: false }) + // The store is shared with the legacy Python app and can be reached by a + // second copy of this app, so a writer lock is normal. Without a busy + // timeout every concurrent access fails instantly with SQLITE_BUSY. + for (const pragma of ['PRAGMA busy_timeout = 10000', 'PRAGMA journal_mode = WAL', 'PRAGMA foreign_keys = ON']) { + try { + db.exec(pragma) + } catch { + /* older/locked stores may refuse a mode change — keep the connection */ + } + } ensureRuntimeSchema(db) currentPath = path + lastOpenError = null + } catch (e) { + lastOpenError = e instanceof Error ? e.message : String(e) + db = null + return false + } + // Agent attribution is a best-effort backfill over potentially huge raw_json + // blobs. It must never take the whole database down with it. + try { if (getSettingText('thread_agent_attribution_v1') !== '1') { refreshConversationAgentAttribution() setSettingText('thread_agent_attribution_v1', '1') } - return true - } catch { - db = null - return false + } catch (e) { + lastOpenError = `attribution-backfill-failed: ${e instanceof Error ? e.message : String(e)}` } + return true } export function dbReady(): boolean { @@ -451,7 +480,7 @@ function interactionWhere(f: InsightsFilters): { where: string; params: Array( @@ -633,6 +662,25 @@ export interface ConvFilters { } export const UNKNOWN_CONVERSATION_AGENT_KEY = '__unknown__' /** True when a label is just a raw conversation/GUID id (no human name). */ +/** + * `%` and `_` in operator-supplied search text are LIKE wildcards. Passing them + * through verbatim made a search for "50%" match every row; escape them and pair + * every LIKE with ESCAPE '\\'. + */ +export function likeNeedle(search: string): string { + const escaped = search.trim().toLowerCase().replace(/[\\%_]/g, (c) => `\\${c}`) + return `%${escaped}%` +} + +/** + * Timestamps are stored with millisecond precision, so a `<= "…T23:59:59Z"` + * bound silently dropped the last second of the range. Use the inclusive + * end-of-day instant instead. + */ +export function endOfDay(date: string): string { + return `${date}T23:59:59.999Z` +} + function looksLikeId(s: string | null): boolean { return !!s && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s.trim()) } @@ -815,19 +863,19 @@ function conversationWhere(f: ConvFilters): { where: string; params: Array): void { db.prepare(sql).run(...params) } +/** + * Run `fn` inside a single IMMEDIATE transaction, rolling back on any error. + * Nested calls reuse the outermost transaction so callers can compose safely. + * Without this, multi-statement writes (delete-then-insert, reset-then-set) + * leave the store in a half-written state if the process dies mid-way. + */ +let txDepth = 0 +export function transaction(fn: () => T): T { + if (!db) throw new Error('db not open') + if (txDepth > 0) return fn() + const handle = db + handle.exec('BEGIN IMMEDIATE') + txDepth++ + try { + const result = fn() + handle.exec('COMMIT') + return result + } catch (e) { + try { + handle.exec('ROLLBACK') + } catch { + /* connection already unwound — surface the original error */ + } + throw e + } finally { + txDepth-- + } +} + export interface UserUpsert { id: string upn: string | null @@ -1273,17 +1350,21 @@ export interface UserUpsert { enabled: boolean } export function upsertUsers(users: UserUpsert[]): void { - for (const u of users) { - run( - `INSERT INTO users(id, upn, display_name, enabled) VALUES(?,?,?,?) + transaction(() => { + for (const u of users) { + run( + `INSERT INTO users(id, upn, display_name, enabled) VALUES(?,?,?,?) ON CONFLICT(id) DO UPDATE SET upn=excluded.upn, display_name=excluded.display_name, enabled=excluded.enabled`, - [u.id, u.upn, u.displayName, u.enabled ? 1 : 0] - ) - } + [u.id, u.upn, u.displayName, u.enabled ? 1 : 0] + ) + } + }) } export function setCopilotLicensed(ids: string[]): void { - run('UPDATE users SET has_copilot_license=0', []) - for (const id of ids) run('UPDATE users SET has_copilot_license=1 WHERE id=?', [id]) + transaction(() => { + run('UPDATE users SET has_copilot_license=0', []) + for (const id of ids) run('UPDATE users SET has_copilot_license=1 WHERE id=?', [id]) + }) } export interface InteractionUpsert { @@ -1300,7 +1381,11 @@ export interface InteractionUpsert { rawJson: string sourceType: string } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertInteractions(rows: InteractionUpsert[]): void { + return transaction(() => upsertInteractionsRows(rows)) +} +function upsertInteractionsRows(rows: InteractionUpsert[]): void { const fetchedAt = new Date().toISOString() for (const r of rows) { run( @@ -1358,7 +1443,11 @@ export interface AuditEventRow { raw_json: string fetched_at: string } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertAuditEvents(rows: AuditEventRow[]): number { + return transaction(() => upsertAuditEventsRows(rows)) +} +function upsertAuditEventsRows(rows: AuditEventRow[]): number { for (const e of rows) { run( `INSERT INTO audit_events(id,source,event_time,user_id,upn,operation,workload,app,target_resources,client_ip,result,raw_json,fetched_at) @@ -1468,7 +1557,11 @@ export interface UsageSnapshotRow { last_activity_bizchat: string | null raw_json: string | null } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertUsageSnapshots(snaps: UsageSnapshotRow[]): number { + return transaction(() => upsertUsageSnapshotsRows(snaps)) +} +function upsertUsageSnapshotsRows(snaps: UsageSnapshotRow[]): number { for (const s of snaps) { const userKey = s.user_id || s.upn || '_total' const sid = createHash('sha1').update(`${s.snapshot_date}|${s.period}|${userKey}`).digest('hex').slice(0, 32) @@ -1537,7 +1630,11 @@ export interface CopilotAgentRow { raw_json: string | null captured_at: string } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertCopilotAgents(rows: CopilotAgentRow[]): number { + return transaction(() => upsertCopilotAgentsRows(rows)) +} +function upsertCopilotAgentsRows(rows: CopilotAgentRow[]): number { let n = 0 for (const r of rows) { if (!r.id) continue @@ -1564,8 +1661,10 @@ export function upsertCopilotAgents(rows: CopilotAgentRow[]): number { return n } export function replaceCopilotAgentsForSource(source: string, rows: CopilotAgentRow[]): number { - run('DELETE FROM copilot_agents WHERE source=?', [source]) - return upsertCopilotAgents(rows.filter((r) => r.source === source)) + return transaction(() => { + run('DELETE FROM copilot_agents WHERE source=?', [source]) + return upsertCopilotAgents(rows.filter((r) => r.source === source)) + }) } // ---- power platform consumption ----------------------------------------- @@ -1582,7 +1681,11 @@ export interface ConsumptionRow { window_end: string | null raw_json: string | null } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertConsumptionRows(rows: ConsumptionRow[]): number { + return transaction(() => upsertConsumptionRowsRows(rows)) +} +function upsertConsumptionRowsRows(rows: ConsumptionRow[]): number { const now = new Date().toISOString() for (const c of rows) { const userKey = c.user_id || (c.environment_id ? `_env:${c.environment_id}` : '_total') @@ -1696,28 +1799,48 @@ export function deleteUserThreads(userId: string, sourceType: string): void { } export function upsertThreads(threads: ThreadGroup[], sourceType: string): void { const now = new Date().toISOString() - for (const t of threads) { - run( - `INSERT OR REPLACE INTO conversation_threads(id,user_id,started_at,ended_at,app,turn_count,prompt_count,response_count,session_ids,topic_keywords,title,cluster_label,computed_at,source_type) - VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)`, - [ - t.id, - t.userId, - t.startedAt, - t.endedAt, - t.app, - t.turnCount, - t.promptCount, - t.responseCount, - JSON.stringify(t.sessionIds), - JSON.stringify([]), - t.title, - null, - now, - sourceType - ] - ) - } + // NOTE: deliberately NOT `INSERT OR REPLACE`. That is a DELETE+INSERT in + // SQLite, which would blank the agent_key/agent_id/agent_name columns added + // by ensureRuntimeSchema() — attribution is recomputed only once per profile, + // so every re-collection would permanently drop it. + transaction(() => { + for (const t of threads) { + run( + `INSERT INTO conversation_threads(id,user_id,started_at,ended_at,app,turn_count,prompt_count,response_count,session_ids,topic_keywords,title,cluster_label,computed_at,source_type) + VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?) + ON CONFLICT(id) DO UPDATE SET + user_id=excluded.user_id, + started_at=excluded.started_at, + ended_at=excluded.ended_at, + app=excluded.app, + turn_count=excluded.turn_count, + prompt_count=excluded.prompt_count, + response_count=excluded.response_count, + session_ids=excluded.session_ids, + topic_keywords=excluded.topic_keywords, + title=excluded.title, + cluster_label=excluded.cluster_label, + computed_at=excluded.computed_at, + source_type=excluded.source_type`, + [ + t.id, + t.userId, + t.startedAt, + t.endedAt, + t.app, + t.turnCount, + t.promptCount, + t.responseCount, + JSON.stringify(t.sessionIds), + JSON.stringify([]), + t.title, + null, + now, + sourceType + ] + ) + } + }) } export function assignThreadsToInteractions(pairs: Array<[string, string]>): void { for (const [interactionId, threadId] of pairs) { @@ -1784,7 +1907,15 @@ export interface SecurityEventRow { raw: string } export interface SecurityEventsDTO { - kpis: { total: number; blocked: number; uniqueUsers: number; topOperation: string | null; topOperationCount: number } + kpis: { + total: number + blocked: number + uniqueUsers: number + topOperation: string | null + topOperationCount: number + /** True when `events` is a truncated page of a larger result set. */ + truncated: boolean + } events: SecurityEventRow[] } export function securityEvents(f: AuditFilters): SecurityEventsDTO { @@ -1800,12 +1931,12 @@ export function securityEvents(f: AuditFilters): SecurityEventsDTO { } if (f.dateTo) { clauses.push('event_time <= ?') - params.push(`${f.dateTo}T23:59:59Z`) + params.push(endOfDay(f.dateTo)) } if (f.search && f.search.trim()) { - const needle = `%${f.search.trim().toLowerCase()}%` + const needle = likeNeedle(f.search) clauses.push( - "(LOWER(COALESCE(operation,'')) LIKE ? OR LOWER(COALESCE(upn,'')) LIKE ? OR LOWER(COALESCE(user_id,'')) LIKE ? OR LOWER(COALESCE(app,'')) LIKE ? OR LOWER(COALESCE(workload,'')) LIKE ?)" + String.raw`(LOWER(COALESCE(operation,'')) LIKE ? ESCAPE '\' OR LOWER(COALESCE(upn,'')) LIKE ? ESCAPE '\' OR LOWER(COALESCE(user_id,'')) LIKE ? ESCAPE '\' OR LOWER(COALESCE(app,'')) LIKE ? ESCAPE '\' OR LOWER(COALESCE(workload,'')) LIKE ? ESCAPE '\')` ) params.push(needle, needle, needle, needle, needle) } @@ -1840,21 +1971,33 @@ export function securityEvents(f: AuditFilters): SecurityEventsDTO { result: r.result, raw: r.raw_json })) - const blocked = events.filter((e) => { - const x = (e.result || '').toLowerCase() - return x.includes('denied') || x.includes('blocked') || x === 'failure' - }).length - const uniqueUsers = new Set(events.filter((e) => e.user !== '—').map((e) => e.user)).size - const opCounts = new Map() - for (const e of events) opCounts.set(e.operation, (opCounts.get(e.operation) ?? 0) + 1) - const topOp = [...opCounts.entries()].sort((a, b) => b[1] - a[1])[0] + // KPIs must describe the whole filtered set, not the truncated page that is + // displayed: counting the returned rows reported "1,000 events" for every + // tenant large enough to hit the limit, which is exactly the population a + // security dashboard must not understate. + const total = get<{ n: number }>(`SELECT COUNT(*) n FROM audit_events ${where}`, ...params)?.n ?? 0 + const blocked = + get<{ n: number }>( + `SELECT COUNT(*) n FROM audit_events ${where}${where ? ' AND' : ' WHERE'} (LOWER(COALESCE(result,'')) LIKE '%denied%' OR LOWER(COALESCE(result,'')) LIKE '%blocked%' OR LOWER(COALESCE(result,'')) = 'failure')`, + ...params + )?.n ?? 0 + const uniqueUsers = + get<{ n: number }>( + `SELECT COUNT(DISTINCT COALESCE(NULLIF(upn, ''), user_id)) n FROM audit_events ${where}${where ? ' AND' : ' WHERE'} (COALESCE(NULLIF(upn, ''), user_id) IS NOT NULL)`, + ...params + )?.n ?? 0 + const topOp = get<{ operation: string | null; c: number }>( + `SELECT operation, COUNT(*) c FROM audit_events ${where} GROUP BY operation ORDER BY c DESC LIMIT 1`, + ...params + ) return { kpis: { - total: events.length, + total, blocked, uniqueUsers, - topOperation: topOp?.[0] ?? null, - topOperationCount: topOp?.[1] ?? 0 + topOperation: topOp?.operation ?? null, + topOperationCount: topOp?.c ?? 0, + truncated: rows.length >= limit && total > rows.length }, events } @@ -2046,8 +2189,10 @@ export function countEdiscoveryConversations(userId: string): { interactions: nu return { interactions, threads } } export function deleteEdiscoveryConversations(userId: string): void { - run("DELETE FROM interactions WHERE source_type='ediscovery' AND user_id=?", [userId]) - run("DELETE FROM conversation_threads WHERE source_type='ediscovery' AND user_id=?", [userId]) + transaction(() => { + run("DELETE FROM interactions WHERE source_type='ediscovery' AND user_id=?", [userId]) + run("DELETE FROM conversation_threads WHERE source_type='ediscovery' AND user_id=?", [userId]) + }) } export function upsertEdiscoveryJob(j: EdiscoveryJob): void { run( @@ -2489,7 +2634,15 @@ export interface CreditDelta { latest_quantity: number last_date: string } +const DELTA_ENTITY_COLS = ['product', 'user_id'] as const + +/** + * `entityCol` is interpolated into SQL because SQLite cannot bind identifiers. + * The union type already constrains callers; this guard makes the invariant + * hold at runtime too, so a future caller cannot turn it into an injection. + */ function creditDeltaSeries(reportType: string, entityCol: 'product' | 'user_id', days: number): DeltaRow[] { + if (!DELTA_ENTITY_COLS.includes(entityCol)) throw new Error(`Unsupported entity column: ${entityCol}`) const sql = `SELECT ${entityCol} AS k, environment_id, environment_name, usage_date, quantity, unit, ` + `quantity - LAG(quantity) OVER (PARTITION BY ${entityCol} ORDER BY usage_date) AS delta ` + @@ -2710,7 +2863,11 @@ export interface FlowRunRow { created_on: string | null raw_json: string | null } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertFlowRuns(rows: FlowRunRow[]): number { + return transaction(() => upsertFlowRunsRows(rows)) +} +function upsertFlowRunsRows(rows: FlowRunRow[]): number { const now = new Date().toISOString() for (const r of rows) { run( @@ -2814,7 +2971,11 @@ export interface AgentDefinitionRow { modified_by: string | null modified_on: string | null } +/** Bulk write — single transaction: atomic on crash and far faster than per-row implicit commits. */ export function upsertAgentDefinitions(rows: AgentDefinitionRow[]): number { + return transaction(() => upsertAgentDefinitionsRows(rows)) +} +function upsertAgentDefinitionsRows(rows: AgentDefinitionRow[]): number { const now = new Date().toISOString() for (const r of rows) { run( diff --git a/src/main/devHarness.ts b/src/main/devHarness.ts new file mode 100644 index 0000000..93eda8b --- /dev/null +++ b/src/main/devHarness.ts @@ -0,0 +1,354 @@ +import { app } from 'electron' +import { join } from 'path' +import * as realdb from './db' +import * as profiles from './profiles' +import { runCollection } from './collector' +import { evaluateCreditAlerts } from './collectors/creditAlerts' +import { toCsv } from './csv' + +/** + * Environment-variable driven smoke harness kept from the Python -> Electron + * port. Each branch runs one backend path headlessly, dumps JSON to %TEMP% and + * quits. + * + * It is imported lazily and ONLY in unpackaged builds (see index.ts), so a + * stray CWT_* variable can never redirect a shipped app into a test mode. + * Returns true when a branch ran — the caller must then not open a window. + */ +export async function runDevHarness(): Promise { + if (process.env.CWT_COLLECT_TEST) { + const fs = await import('node:fs') + const out = join(process.env.TEMP || '.', 'cwt_collect_out.txt') + fs.writeFileSync(out, '') + try { + const res = await runCollection( + 'manual', + (p) => fs.appendFileSync(out, `${p.phase} ${p.percent}% ${p.message}\n`), + { maxUsers: Number(process.env.CWT_COLLECT_TEST) || 1, forceBackfill: true } + ) + fs.appendFileSync(out, 'RESULT ' + JSON.stringify(res) + '\n') + } catch (e) { + fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') + } + app.quit() + return true + } + + if (process.env.CWT_AUDIT_TEST) { + const fs = await import('node:fs') + const { collectAudit } = await import('./collectors/audit') + const out = join(process.env.TEMP || '.', 'cwt_audit_out.txt') + fs.writeFileSync(out, '') + try { + const res = await collectAudit((line) => fs.appendFileSync(out, line + '\n')) + fs.appendFileSync(out, 'RESULT ' + JSON.stringify(res) + '\n') + } catch (e) { + fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') + } + app.quit() + return true + } + + if (process.env.CWT_USAGE_TEST) { + const fs = await import('node:fs') + const { collectCopilotUsage } = await import('./collectors/usage') + const out = join(process.env.TEMP || '.', 'cwt_usage_out.txt') + fs.writeFileSync(out, '') + try { + const n = await collectCopilotUsage(process.env.CWT_USAGE_TEST === '1' ? 'D30' : process.env.CWT_USAGE_TEST!) + fs.appendFileSync(out, 'RESULT rows=' + n + '\n') + } catch (e) { + fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') + } + app.quit() + return true + } + + if (process.env.CWT_DIAG_TEST) { + const fs = await import('node:fs') + const { collectAdminDiagnostics } = await import('./collectors/agents') + const out = join(process.env.TEMP || '.', 'cwt_diag_out.txt') + fs.writeFileSync(out, '') + try { + const res = await collectAdminDiagnostics((line) => fs.appendFileSync(out, line + '\n')) + fs.appendFileSync(out, 'RESULT ' + JSON.stringify(res) + '\n') + } catch (e) { + fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') + } + app.quit() + return true + } + + if (process.env.CWT_CONV_TEST) { + const fs = await import('node:fs') + const out = join(process.env.TEMP || '.', 'cwt_conv_out.txt') + try { + const users = realdb.conversationUsers('api') + const apps = realdb.conversationApps('api') + const sampleUser = users[0]?.id + const sampleApp = apps[0]?.value + // Pull a search needle from the first thread title so the LIKE filter has a hit. + const firstTitle = realdb.conversations({ limit: 1, source: 'api' })[0]?.title || '' + const needle = firstTitle.split(' ')[0] || firstTitle.slice(0, 4) + const r = { + counts: { + api: realdb.conversations({ limit: 2000, source: 'api' }).length, + dataverse: realdb.conversations({ limit: 2000, source: 'dataverse' }).length, + ediscovery: realdb.conversations({ limit: 2000, source: 'ediscovery' }).length, + all: realdb.conversations({ limit: 2000 }).length + }, + users: { count: users.length, sample: users.slice(0, 3) }, + apps, + filters: { + byUser: sampleUser + ? realdb.conversations({ source: 'api', userId: sampleUser }).length + : 'n/a', + byApp: sampleApp ? realdb.conversations({ source: 'api', app: sampleApp }).length : 'n/a', + searchTitle: needle + ? realdb.conversations({ source: 'api', search: needle, scope: 'title' }).length + : 'n/a', + searchBody: needle + ? realdb.conversations({ source: 'api', search: needle, scope: 'body' }).length + : 'n/a', + searchAll: needle + ? realdb.conversations({ source: 'api', search: needle, scope: 'all' }).length + : 'n/a', + searchNoMatch: realdb.conversations({ source: 'api', search: '___zzz_nomatch___' }).length, + dateFuture: realdb.conversations({ source: 'api', dateFrom: '2999-01-01' }).length + }, + needle, + backCompat: realdb.conversations(3, 'api').map((c) => ({ id: c.id, title: c.title })) + } + fs.writeFileSync(out, JSON.stringify(r, null, 2)) + } catch (e) { + fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + } + app.quit() + return true + } + + if (process.env.CWT_PROFILE_TEST) { + const fs = await import('node:fs') + const np = await import('node:path') + const out = join(process.env.TEMP || '.', 'cwt_profile_out.txt') + try { + const before = profiles.listProfiles() + const temp = profiles.createProfile('__cwt_del_test__') + const dir = np.join(profiles.rootDir(), 'profiles', temp.id) + const afterCreate = profiles.listProfiles() + const folderExists = fs.existsSync(dir) + const dbExists = fs.existsSync(np.join(dir, 'store.db')) + const deleted = profiles.deleteProfile(temp.id) + const afterDelete = profiles.listProfiles() + fs.writeFileSync( + out, + JSON.stringify( + { + beforeCount: before.profiles.length, + activeBefore: before.activeId, + tempId: temp.id, + afterCreateCount: afterCreate.profiles.length, + folderExists, + dbExists, + deleted, + afterDeleteCount: afterDelete.profiles.length, + activeAfter: afterDelete.activeId, + folderGone: !fs.existsSync(dir), + activeUnchanged: before.activeId === afterDelete.activeId, + roundTripClean: before.profiles.length === afterDelete.profiles.length + }, + null, + 2 + ) + ) + } catch (e) { + fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + } + app.quit() + return true + } + + if (process.env.CWT_DTO_TEST) { + const fs = await import('node:fs') + const out = join(process.env.TEMP || '.', 'cwt_dto_out.txt') + try { + const result = { + dashboard: realdb.dashboardSummary(), + insights: realdb.insightsData({}), + agents: realdb.agentsOverview({ thresholdDays: 30 }), + identityEvents: realdb.agentIdentityEvents(200), + security: realdb.securityEvents({ limit: 2000 }), + consumption: realdb.consumptionExplorer(), + audit: realdb.auditCollectStatus(), + usage: realdb.usageCollectStatus(), + diagnostics: realdb.diagnosticsStatus(), + conversation: realdb.conversationCollectStatus(), + agentCredit: realdb.agentCreditOverview(), + alertsEvaluated: evaluateCreditAlerts(), + alerts: realdb.listCreditAlerts('active') + } + fs.writeFileSync(out, JSON.stringify(result, null, 2)) + } catch (e) { + fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + } + app.quit() + return true + } + + if (process.env.CWT_EXPORT_TEST) { + const fs = await import('node:fs') + const out = join(process.env.TEMP || '.', 'cwt_export_out.txt') + try { + const stat = realdb.dbStat() + const rows = realdb.exportTableRows('copilot_admin_diagnostics') + const csv = toCsv(rows) + const csvPath = join(process.env.TEMP || '.', 'cwt_export_sample.csv') + fs.writeFileSync(csvPath, '\ufeff' + csv, 'utf-8') + fs.writeFileSync( + out, + JSON.stringify( + { dbPath: stat.path, tables: stat.tables, sampleRows: rows.length, csvHead: csv.slice(0, 200), csvPath }, + null, + 2 + ) + ) + } catch (e) { + fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + } + app.quit() + return true + } + + if (process.env.CWT_EDISC_TEST) { + const fs = await import('node:fs') + const { parseExportPackage, splitCopilotBody } = await import('./collectors/ediscoveryExport') + const out = join(process.env.TEMP || '.', 'cwt_edisc_out.txt') + function makeZip(name: string, content: string): Buffer { + const nameBuf = Buffer.from(name, 'utf8') + const data = Buffer.from(content, 'utf8') + const lfh = Buffer.alloc(30) + lfh.writeUInt32LE(0x04034b50, 0) + lfh.writeUInt16LE(20, 4) + lfh.writeUInt32LE(data.length, 18) + lfh.writeUInt32LE(data.length, 22) + lfh.writeUInt16LE(nameBuf.length, 26) + const localPart = Buffer.concat([lfh, nameBuf, data]) + const cdh = Buffer.alloc(46) + cdh.writeUInt32LE(0x02014b50, 0) + cdh.writeUInt32LE(data.length, 20) + cdh.writeUInt32LE(data.length, 24) + cdh.writeUInt16LE(nameBuf.length, 28) + cdh.writeUInt32LE(0, 42) + const cdPart = Buffer.concat([cdh, nameBuf]) + const eocd = Buffer.alloc(22) + eocd.writeUInt32LE(0x06054b50, 0) + eocd.writeUInt16LE(1, 8) + eocd.writeUInt16LE(1, 10) + eocd.writeUInt32LE(cdPart.length, 12) + eocd.writeUInt32LE(localPart.length, 16) + return Buffer.concat([localPart, cdPart, eocd]) + } + try { + const rec = { + id: 'i1', + conversationId: 'c1', + createdDateTime: '2026-06-01T10:00:00Z', + prompt: '계약서 요약해줘', + response: '요약 결과입니다.', + app: 'BizChat' + } + const zip = makeZip('items.json', JSON.stringify([rec])) + const rows = parseExportPackage(zip, 'user-1') + const split = splitCopilotBody('User: 안녕하세요\nCopilot: 반갑습니다') + fs.writeFileSync( + out, + JSON.stringify( + { + rowCount: rows.length, + rows: rows.map((r) => ({ type: r.interactionType, body: r.bodyText, session: r.sessionId, source: r.sourceType, req: r.requestId })), + split + }, + null, + 2 + ) + ) + } catch (e) { + fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + } + app.quit() + return true + } + + if (process.env.CWT_DVPARSE_TEST) { + const fs = await import('node:fs') + const { parseConversationTranscript, parseEnvironmentsJson, parseFlowRunRecord } = await import('./collectors/dataverse') + const { analyzeAgent } = await import('./collectors/agentRisk') + const out = join(process.env.TEMP || '.', 'cwt_dvparse_out.txt') + try { + const content = JSON.stringify({ + activities: [ + { type: 'message', id: 'a1', from: { aadObjectId: 'aad-123', name: '홍길동' }, text: '안녕 에이전트', channelId: 'msteams', timestamp: 1780000000, conversation: { id: 'conv-1' } }, + { type: 'message', id: 'a2', from: { role: 0, name: 'Agent' }, recipient: { aadObjectId: 'aad-123' }, text: '안녕하세요!', channelId: 'msteams', timestamp: 1780000005 }, + { type: 'message', id: 'a3', from: { id: 'webuser' }, text: 'web only', channelId: 'webchat', timestamp: 1780000010 } + ] + }) + const all = parseConversationTranscript(content, { transcriptId: 't1', environmentId: 'env1', teamsOnly: false }) + const teams = parseConversationTranscript(content, { transcriptId: 't1', environmentId: 'env1', teamsOnly: true }) + const envs = parseEnvironmentsJson({ + value: [{ ApiUrl: 'https://contoso.crm.dynamics.com/api/data/v9.0/', Id: 'e1', FriendlyName: 'Contoso' }] + }) + const flow = parseFlowRunRecord( + { + flowrunid: 'run-1', + status: 'Failed', + starttime: '2026-06-20T01:00:00Z', + duration: '4200', + modernflowtype: 2, + _workflow_value: 'wf-1', + '_workflow_value@OData.Community.Display.V1.FormattedValue': '주문 처리 플로우', + _ownerid_value: 'owner-1', + '_ownerid_value@OData.Community.Display.V1.FormattedValue': '김철수', + createdon: '2026-06-20T01:00:05Z' + }, + 'env1', + 'Contoso' + ) + const risk = analyzeAgent([ + { componenttype: 5 }, + { componenttype: 1, data: 'httprequest connectorid foreach while invoketool' } + ]) + fs.writeFileSync( + out, + JSON.stringify( + { + allRows: all.rows.length, + allTypes: all.rows.map((r) => r.interactionType), + apps: all.rows.map((r) => r.app), + createdAts: all.rows.map((r) => r.createdAt), + participants: [...all.participants], + teamsRows: teams.rows.length, + teamsSkippedNonTeams: teams.skippedNonTeams, + envs, + flow, + risk: { + score: risk.score, + band: risk.band, + hasTrigger: risk.hasTrigger, + external: risk.externalCallCount, + tools: risk.toolCount, + loops: risk.loopCount + } + }, + null, + 2 + ) + ) + } catch (e) { + fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + } + app.quit() + return true + } + + return false +} diff --git a/src/main/graph.ts b/src/main/graph.ts index 40ce033..e445a82 100644 --- a/src/main/graph.ts +++ b/src/main/graph.ts @@ -1,8 +1,10 @@ /** * Microsoft Graph client (app-only), ported from services/graph.py. - * Uses built-in fetch + OData @odata.nextLink pagination. + * Uses the shared HTTP client (hard timeout + 429/5xx backoff + one-shot 401 + * refresh) and OData @odata.nextLink pagination. */ import { getAppToken, resetAuth } from './auth' +import { httpRequest, type HttpOptions } from './http' const BETA = 'https://graph.microsoft.com/beta' const V1 = 'https://graph.microsoft.com/v1.0' @@ -21,31 +23,43 @@ interface ODataPage { ['@odata.nextLink']?: string } -const sleep = (ms: number): Promise => new Promise((r) => setTimeout(r, ms)) -const MAX_THROTTLE_RETRIES = 5 -/** Wait time for a 429: honor Retry-After header, else exponential backoff, cap 60s. */ -function throttleDelayMs(res: Response, attempt: number): number { - const hdr = Number(res.headers.get('retry-after')) - const fromHdr = Number.isFinite(hdr) && hdr > 0 ? hdr * 1000 : 0 - return Math.min(60000, Math.max(fromHdr, 1000 * 2 ** attempt)) +/** On 401, drop the cached app token so the single retry mints a fresh one. */ +const graphAuthRetry: HttpOptions = { + onUnauthorized: () => { + resetAuth() + return true + } } -async function graphGet(url: string, retry = true, attempt = 0): Promise { +async function graphFetch(url: string, init: RequestInit = {}, opts: HttpOptions = {}): Promise { const token = await getAppToken() - const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }) - if (res.status === 401 && retry) { - resetAuth() - return graphGet(url, false) - } - if (res.status === 429 && attempt < MAX_THROTTLE_RETRIES) { - await sleep(throttleDelayMs(res, attempt)) - return graphGet(url, retry, attempt + 1) - } + return httpRequest( + url, + { + ...init, + headers: { ...((init.headers as Record) ?? {}), Authorization: `Bearer ${token}` } + }, + { ...graphAuthRetry, ...opts } + ) +} + +async function graphJson(url: string, init: RequestInit = {}, opts: HttpOptions = {}): Promise { + const res = await graphFetch(url, init, opts) if (!res.ok) { - const body = await res.text() + const body = await res.text().catch(() => '') throw new GraphError(res.status, `Graph ${res.status} ${url.slice(0, 90)} :: ${body.slice(0, 200)}`) } - return (await res.json()) as ODataPage + const text = await res.text() + if (!text.trim()) return {} as T + try { + return JSON.parse(text) as T + } catch { + throw new GraphError(res.status, `Graph ${res.status} ${url.slice(0, 90)} :: non-JSON response body`) + } +} + +async function graphGet(url: string): Promise { + return graphJson(url) } export interface GraphUser { @@ -104,44 +118,21 @@ export async function* listInteractions(userId: string, since: string | null): A // ---- raw GET / POST helpers (non-OData payloads) ------------------------ -async function graphGetOne(url: string, retry = true, attempt = 0): Promise> { - const token = await getAppToken() - const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }) - if (res.status === 401 && retry) { - resetAuth() - return graphGetOne(url, false) - } - if (res.status === 429 && attempt < MAX_THROTTLE_RETRIES) { - await sleep(throttleDelayMs(res, attempt)) - return graphGetOne(url, retry, attempt + 1) - } - if (!res.ok) { - const body = await res.text() - throw new GraphError(res.status, `Graph ${res.status} ${url.slice(0, 90)} :: ${body.slice(0, 200)}`) - } - return (await res.json()) as Record +async function graphGetOne(url: string): Promise> { + return graphJson>(url) } -async function graphPost(url: string, body: unknown, retry = true, attempt = 0): Promise> { - const token = await getAppToken() - const res = await fetch(url, { +/** + * POST is retried on 429 only. A 429 means Graph explicitly did not process + * the request, so replaying it is safe; a 5xx leaves the outcome unknown and + * a blind retry could duplicate a submitted query. + */ +async function graphPost(url: string, body: unknown): Promise> { + return graphJson>(url, { method: 'POST', - headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) - if (res.status === 401 && retry) { - resetAuth() - return graphPost(url, body, false) - } - if (res.status === 429 && attempt < MAX_THROTTLE_RETRIES) { - await sleep(throttleDelayMs(res, attempt)) - return graphPost(url, body, retry, attempt + 1) - } - if (!res.ok) { - const text = await res.text() - throw new GraphError(res.status, `Graph ${res.status} ${url.slice(0, 90)} :: ${text.slice(0, 200)}`) - } - return (await res.json()) as Record } const GRAPH_DT_RE = /^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.\d+)?(?:Z|\+00:00)?$/ @@ -240,18 +231,17 @@ export async function* listSignIns( // ---- Copilot usage reports (CSV) ---------------------------------------- -async function fetchReportCsv(url: string, retry = true): Promise { - const token = await getAppToken() - const res = await fetch(url, { - headers: { Authorization: `Bearer ${token}`, Accept: 'text/csv, application/octet-stream, */*' }, +/** + * Usage reports are served as CSV (often via a 302 to a storage URL) and are + * throttled aggressively, so they go through the shared client for backoff. + */ +async function fetchReportCsv(url: string): Promise { + const res = await graphFetch(url, { + headers: { Accept: 'text/csv, application/octet-stream, */*' }, redirect: 'follow' }) - if (res.status === 401 && retry) { - resetAuth() - return fetchReportCsv(url, false) - } if (!res.ok) { - const body = await res.text() + const body = await res.text().catch(() => '') throw new GraphError(res.status, `Graph ${res.status} ${url.slice(0, 90)} :: ${body.slice(0, 160)}`) } return res.text() diff --git a/src/main/http.ts b/src/main/http.ts new file mode 100644 index 0000000..2c84723 --- /dev/null +++ b/src/main/http.ts @@ -0,0 +1,169 @@ +/** + * Shared HTTP client for every outbound call the main process makes + * (Graph, Purview eDiscovery, Dataverse, BAP, Power Platform, Entra onboarding). + * + * Before this existed each collector hand-rolled its own `fetch` wrapper, so + * timeout handling, 429 throttling and 401 refresh behaved differently per API + * — and none of them had a timeout at all, which let a single unresponsive + * endpoint hang the whole main process (and with it the UI) indefinitely. + */ + +export class HttpError extends Error { + readonly status: number + readonly url: string + readonly body: string + constructor(status: number, url: string, body: string) { + super(`HTTP ${status} ${url.slice(0, 120)} :: ${body.slice(0, 200)}`) + this.name = 'HttpError' + this.status = status + this.url = url + this.body = body + } +} + +export class HttpTimeoutError extends Error { + readonly url: string + constructor(url: string, timeoutMs: number) { + super(`Request timed out after ${timeoutMs}ms: ${url.slice(0, 120)}`) + this.name = 'HttpTimeoutError' + this.url = url + } +} + +/** Default per-request budget. Long downloads override this explicitly. */ +export const DEFAULT_TIMEOUT_MS = 60_000 +/** Budget for bulk export/blob downloads. */ +export const DOWNLOAD_TIMEOUT_MS = 20 * 60_000 +export const MAX_THROTTLE_RETRIES = 5 + +const RETRYABLE_STATUS = new Set([429, 500, 502, 503, 504]) +const IDEMPOTENT_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']) + +const sleep = (ms: number): Promise => new Promise((r) => setTimeout(r, ms)) + +/** + * Backoff for a throttled/unavailable response: honour `Retry-After` + * (seconds or HTTP-date), otherwise exponential backoff, capped at 60s. + */ +export function retryDelayMs(res: { headers: { get(name: string): string | null } }, attempt: number): number { + const raw = res.headers.get('retry-after') + let fromHeader = 0 + if (raw) { + const seconds = Number(raw) + if (Number.isFinite(seconds) && seconds > 0) { + fromHeader = seconds * 1000 + } else { + const at = Date.parse(raw) + if (Number.isFinite(at)) fromHeader = Math.max(0, at - Date.now()) + } + } + return Math.min(60_000, Math.max(fromHeader, 1000 * 2 ** attempt)) +} + +export interface HttpOptions { + /** Abort the request after this many ms. Defaults to DEFAULT_TIMEOUT_MS. */ + timeoutMs?: number + /** Caller-owned cancellation (user pressed Stop, app quitting, …). */ + signal?: AbortSignal + /** + * Invoked once on 401 before a single retry. Return true to retry — used to + * drop cached tokens and mint a fresh one. + */ + onUnauthorized?: () => Promise | boolean + /** Max retries for 429/5xx. Defaults to MAX_THROTTLE_RETRIES. */ + maxRetries?: number + /** Optional progress/diagnostic sink. Never receives credentials. */ + onRetry?: (info: { url: string; status: number; attempt: number; delayMs: number }) => void + /** Injection seam for tests. */ + fetchImpl?: typeof fetch +} + +function composeSignal(timeoutMs: number, external: AbortSignal | undefined): { + signal: AbortSignal + cleanup: () => void + timedOut: () => boolean +} { + const controller = new AbortController() + let timedOut = false + const timer = setTimeout(() => { + timedOut = true + controller.abort() + }, timeoutMs) + const onExternalAbort = (): void => controller.abort() + if (external) { + if (external.aborted) controller.abort() + else external.addEventListener('abort', onExternalAbort, { once: true }) + } + return { + signal: controller.signal, + cleanup: () => { + clearTimeout(timer) + external?.removeEventListener('abort', onExternalAbort) + }, + timedOut: () => timedOut + } +} + +/** + * Perform a request with a hard timeout, 401-refresh and 429/5xx backoff. + * Non-idempotent methods are retried on 429 only (the server states it did not + * process the request); they are never retried on 5xx, where the outcome is + * unknown and a retry could duplicate work. + */ +export async function httpRequest(url: string, init: RequestInit = {}, opts: HttpOptions = {}): Promise { + const { + timeoutMs = DEFAULT_TIMEOUT_MS, + signal: externalSignal, + onUnauthorized, + maxRetries = MAX_THROTTLE_RETRIES, + onRetry, + fetchImpl = fetch + } = opts + const method = (init.method ?? 'GET').toUpperCase() + const idempotent = IDEMPOTENT_METHODS.has(method) + let refreshed = false + + for (let attempt = 0; ; attempt++) { + const { signal, cleanup, timedOut } = composeSignal(timeoutMs, externalSignal) + let res: Response + try { + res = await fetchImpl(url, { ...init, signal }) + } catch (e) { + cleanup() + if (timedOut()) throw new HttpTimeoutError(url, timeoutMs) + throw e + } + cleanup() + + if (res.status === 401 && onUnauthorized && !refreshed) { + refreshed = true + if (await onUnauthorized()) continue + } + + const retryable = RETRYABLE_STATUS.has(res.status) && (idempotent || res.status === 429) + if (retryable && attempt < maxRetries) { + const delayMs = retryDelayMs(res, attempt) + onRetry?.({ url, status: res.status, attempt, delayMs }) + await sleep(delayMs) + continue + } + return res + } +} + +/** + * `httpRequest` + status check + JSON parse. A body that is not valid JSON is + * an error, never an empty object: silently degrading to `{}` is how a + * governance tool ends up reporting "0 findings" for a failed API call. + */ +export async function httpJson(url: string, init: RequestInit = {}, opts: HttpOptions = {}): Promise { + const res = await httpRequest(url, init, opts) + if (!res.ok) throw new HttpError(res.status, url, await res.text().catch(() => '')) + const text = await res.text() + if (!text.trim()) return undefined as T + try { + return JSON.parse(text) as T + } catch { + throw new HttpError(res.status, url, `expected JSON, got: ${text.slice(0, 200)}`) + } +} diff --git a/src/main/index.ts b/src/main/index.ts index 3fc37e6..1e41ed5 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -37,6 +37,7 @@ import { evaluateCreditAlerts } from './collectors/creditAlerts' import { collectPurview } from './collectors/audit' import type { EventChannel, InvokeChannel } from '../shared/ipc' import { isAllowedPrimaryNavigation, isSafeExternalUrl } from './windowSecurity' +import { toCsv } from './csv' /** * Real backend. Channel names mirror the Python bridge surface @@ -73,6 +74,15 @@ function errMsg(e: unknown): string { return e instanceof Error ? e.message : String(e) } +/** + * Log a diagnostic without leaking PII. Graph/Dataverse errors routinely carry + * response bodies containing UPNs, prompts and tokens, so only the message text + * ever reaches stdout — never the raw error object. + */ +function logError(context: string, e: unknown): void { + console.error(`${context}: ${errMsg(e)}`) +} + function schedulePurviewAttribution(delayMs = 10_000): void { if (purviewAttributionTimer) clearTimeout(purviewAttributionTimer) purviewAttributionTimer = setTimeout(() => void recoverPurviewAttribution(), delayMs) @@ -97,7 +107,7 @@ async function recoverPurviewAttribution(): Promise { else if (outcome.error) schedulePurviewAttribution(900_000) else schedulePurviewAttribution(5_000) } catch (e) { - console.error('Purview agent attribution recovery failed', e) + logError('Purview agent attribution recovery failed', e) schedulePurviewAttribution(900_000) } finally { collectingAudit = false @@ -119,19 +129,6 @@ function capabilityGate(kind: string): { ok: false; error: string; capability: s if (allowsKind(loadCapabilityProfile(), kind)) return null return { ok: false, error: 'license-required', capability: KIND_REQUIRED_CAPABILITY[kind] } } -function toCsv(rows: Record[]): string { - if (!rows.length) return '' - const headers = Object.keys(rows[0]) - const esc = (v: unknown): string => { - if (v === null || v === undefined) return '' - const s = String(v) - return /[",\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s - } - const lines = [headers.join(',')] - for (const r of rows) lines.push(headers.map((h) => esc(r[h])).join(',')) - return lines.join('\r\n') -} - function registerHandlers(): void { realdb.openDb() @@ -142,7 +139,7 @@ function registerHandlers(): void { try { return real() } catch (e) { - console.error(e) + logError('ipc-handler', e) return [] } } @@ -151,7 +148,7 @@ function registerHandlers(): void { try { return real() } catch (e) { - console.error(e) + logError('ipc-handler', e) return null } } @@ -172,7 +169,7 @@ function registerHandlers(): void { try { return realdb.conversations({ limit: 2000, ...f }) } catch (e) { - console.error('conversations_all', e) + logError('conversations_all', e) return [] } } @@ -184,7 +181,7 @@ function registerHandlers(): void { try { return realdb.conversationAgentFacets(f) } catch (e) { - console.error('conversation_agent_facets', e) + logError('conversation_agent_facets', e) return [] } }) @@ -194,7 +191,7 @@ function registerHandlers(): void { try { return realdb.conversationUserFacets(f) } catch (e) { - console.error('conversation_user_facets', e) + logError('conversation_user_facets', e) return [] } }) @@ -204,7 +201,7 @@ function registerHandlers(): void { try { return realdb.conversationPage(f) } catch (e) { - console.error('conversation_page', e) + logError('conversation_page', e) return { rows: [], total: 0, limit: f.limit ?? 50, offset: f.offset ?? 0 } } }) @@ -232,7 +229,7 @@ function registerHandlers(): void { try { return realdb.insightsData(f) } catch (e) { - console.error('insights_data', e) + logError('insights_data', e) return { kpis: { activeUsers: 0, totalUsers: 0, threads: 0, messages: 0, prompts: 0, topApp: null, topAppMessages: 0 }, trend: [], apps: [], users: [] } } }) @@ -262,7 +259,7 @@ function registerHandlers(): void { try { return realdb.agentsOverview(f) } catch (e) { - console.error('agents_overview', e) + logError('agents_overview', e) return { kpis: { total: 0, active: 0, stale: 0, neverUsed: 0, usageEvents: 0, thresholdDays: f.thresholdDays ?? 30 }, agents: [] } } }) @@ -287,7 +284,7 @@ function registerHandlers(): void { try { return fn() } catch (e) { - console.error(e) + logError('ipc-handler', e) return null } } @@ -300,7 +297,7 @@ function registerHandlers(): void { try { return realdb.securityEvents(f) } catch (e) { - console.error('security_events', e) + logError('security_events', e) return { kpis: { total: 0, blocked: 0, uniqueUsers: 0, topOperation: null, topOperationCount: 0 }, events: [] } } }) @@ -310,7 +307,7 @@ function registerHandlers(): void { try { return realdb.consumptionExplorer() } catch (e) { - console.error('consumption_explorer', e) + logError('consumption_explorer', e) return null } }) @@ -1004,7 +1001,7 @@ function registerHandlers(): void { }) } -function createWindow(): void { +function createWindow(): BrowserWindow { const win = new BrowserWindow({ width: 1320, height: 860, @@ -1044,357 +1041,67 @@ function createWindow(): void { } else { win.loadFile(rendererFile) } + return win } -app.whenReady().then(async () => { - registerHandlers() - - if (process.env.CWT_COLLECT_TEST) { - const fs = await import('node:fs') - const out = join(process.env.TEMP || '.', 'cwt_collect_out.txt') - fs.writeFileSync(out, '') - try { - const res = await runCollection( - 'manual', - (p) => fs.appendFileSync(out, `${p.phase} ${p.percent}% ${p.message}\n`), - { maxUsers: Number(process.env.CWT_COLLECT_TEST) || 1, forceBackfill: true } - ) - fs.appendFileSync(out, 'RESULT ' + JSON.stringify(res) + '\n') - } catch (e) { - fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') - } - app.quit() - return - } - - if (process.env.CWT_AUDIT_TEST) { - const fs = await import('node:fs') - const { collectAudit } = await import('./collectors/audit') - const out = join(process.env.TEMP || '.', 'cwt_audit_out.txt') - fs.writeFileSync(out, '') - try { - const res = await collectAudit((line) => fs.appendFileSync(out, line + '\n')) - fs.appendFileSync(out, 'RESULT ' + JSON.stringify(res) + '\n') - } catch (e) { - fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') - } - app.quit() - return - } - - if (process.env.CWT_USAGE_TEST) { - const fs = await import('node:fs') - const { collectCopilotUsage } = await import('./collectors/usage') - const out = join(process.env.TEMP || '.', 'cwt_usage_out.txt') - fs.writeFileSync(out, '') - try { - const n = await collectCopilotUsage(process.env.CWT_USAGE_TEST === '1' ? 'D30' : process.env.CWT_USAGE_TEST!) - fs.appendFileSync(out, 'RESULT rows=' + n + '\n') - } catch (e) { - fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') - } - app.quit() - return - } - - if (process.env.CWT_DIAG_TEST) { - const fs = await import('node:fs') - const { collectAdminDiagnostics } = await import('./collectors/agents') - const out = join(process.env.TEMP || '.', 'cwt_diag_out.txt') - fs.writeFileSync(out, '') - try { - const res = await collectAdminDiagnostics((line) => fs.appendFileSync(out, line + '\n')) - fs.appendFileSync(out, 'RESULT ' + JSON.stringify(res) + '\n') - } catch (e) { - fs.appendFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e)) + '\n') - } - app.quit() - return - } - - if (process.env.CWT_CONV_TEST) { - const fs = await import('node:fs') - const out = join(process.env.TEMP || '.', 'cwt_conv_out.txt') - try { - const users = realdb.conversationUsers('api') - const apps = realdb.conversationApps('api') - const sampleUser = users[0]?.id - const sampleApp = apps[0]?.value - // Pull a search needle from the first thread title so the LIKE filter has a hit. - const firstTitle = realdb.conversations({ limit: 1, source: 'api' })[0]?.title || '' - const needle = firstTitle.split(' ')[0] || firstTitle.slice(0, 4) - const r = { - counts: { - api: realdb.conversations({ limit: 2000, source: 'api' }).length, - dataverse: realdb.conversations({ limit: 2000, source: 'dataverse' }).length, - ediscovery: realdb.conversations({ limit: 2000, source: 'ediscovery' }).length, - all: realdb.conversations({ limit: 2000 }).length - }, - users: { count: users.length, sample: users.slice(0, 3) }, - apps, - filters: { - byUser: sampleUser - ? realdb.conversations({ source: 'api', userId: sampleUser }).length - : 'n/a', - byApp: sampleApp ? realdb.conversations({ source: 'api', app: sampleApp }).length : 'n/a', - searchTitle: needle - ? realdb.conversations({ source: 'api', search: needle, scope: 'title' }).length - : 'n/a', - searchBody: needle - ? realdb.conversations({ source: 'api', search: needle, scope: 'body' }).length - : 'n/a', - searchAll: needle - ? realdb.conversations({ source: 'api', search: needle, scope: 'all' }).length - : 'n/a', - searchNoMatch: realdb.conversations({ source: 'api', search: '___zzz_nomatch___' }).length, - dateFuture: realdb.conversations({ source: 'api', dateFrom: '2999-01-01' }).length - }, - needle, - backCompat: realdb.conversations(3, 'api').map((c) => ({ id: c.id, title: c.title })) - } - fs.writeFileSync(out, JSON.stringify(r, null, 2)) - } catch (e) { - fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) - } - app.quit() - return - } +/** + * Only one copy of the app may own a profile's SQLite store. The portable build + * makes double-launching easy, and two writers on the same store.db produce + * SQLITE_BUSY failures and half-applied collection runs. + */ +function focusExistingWindow(): void { + const [win] = BrowserWindow.getAllWindows() + if (!win) return + if (win.isMinimized()) win.restore() + win.show() + win.focus() +} - if (process.env.CWT_PROFILE_TEST) { - const fs = await import('node:fs') - const np = await import('node:path') - const out = join(process.env.TEMP || '.', 'cwt_profile_out.txt') - try { - const before = profiles.listProfiles() - const temp = profiles.createProfile('__cwt_del_test__') - const dir = np.join(profiles.rootDir(), 'profiles', temp.id) - const afterCreate = profiles.listProfiles() - const folderExists = fs.existsSync(dir) - const dbExists = fs.existsSync(np.join(dir, 'store.db')) - const deleted = profiles.deleteProfile(temp.id) - const afterDelete = profiles.listProfiles() - fs.writeFileSync( - out, - JSON.stringify( - { - beforeCount: before.profiles.length, - activeBefore: before.activeId, - tempId: temp.id, - afterCreateCount: afterCreate.profiles.length, - folderExists, - dbExists, - deleted, - afterDeleteCount: afterDelete.profiles.length, - activeAfter: afterDelete.activeId, - folderGone: !fs.existsSync(dir), - activeUnchanged: before.activeId === afterDelete.activeId, - roundTripClean: before.profiles.length === afterDelete.profiles.length - }, - null, - 2 - ) - ) - } catch (e) { - fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) - } - app.quit() - return +let shuttingDown = false +function shutdownDb(): void { + if (shuttingDown) return + shuttingDown = true + if (purviewAttributionTimer) clearTimeout(purviewAttributionTimer) + purviewAttributionTimer = null + try { + realdb.checkpoint() + realdb.closeDb() + } catch (e) { + logError('db shutdown', e) } +} - if (process.env.CWT_DTO_TEST) { - const fs = await import('node:fs') - const out = join(process.env.TEMP || '.', 'cwt_dto_out.txt') - try { - const result = { - dashboard: realdb.dashboardSummary(), - insights: realdb.insightsData({}), - agents: realdb.agentsOverview({ thresholdDays: 30 }), - identityEvents: realdb.agentIdentityEvents(200), - security: realdb.securityEvents({ limit: 2000 }), - consumption: realdb.consumptionExplorer(), - audit: realdb.auditCollectStatus(), - usage: realdb.usageCollectStatus(), - diagnostics: realdb.diagnosticsStatus(), - conversation: realdb.conversationCollectStatus(), - agentCredit: realdb.agentCreditOverview(), - alertsEvaluated: evaluateCreditAlerts(), - alerts: realdb.listCreditAlerts('active') - } - fs.writeFileSync(out, JSON.stringify(result, null, 2)) - } catch (e) { - fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) - } - app.quit() - return - } +// A rejected promise inside a collector must not take the whole app down: +// Node's default for unhandled rejections is to throw and exit. +process.on('unhandledRejection', (reason) => logError('unhandledRejection', reason)) +process.on('uncaughtException', (e) => logError('uncaughtException', e)) - if (process.env.CWT_EXPORT_TEST) { - const fs = await import('node:fs') - const out = join(process.env.TEMP || '.', 'cwt_export_out.txt') - try { - const stat = realdb.dbStat() - const rows = realdb.exportTableRows('copilot_admin_diagnostics') - const csv = toCsv(rows) - const csvPath = join(process.env.TEMP || '.', 'cwt_export_sample.csv') - fs.writeFileSync(csvPath, '\ufeff' + csv, 'utf-8') - fs.writeFileSync( - out, - JSON.stringify( - { dbPath: stat.path, tables: stat.tables, sampleRows: rows.length, csvHead: csv.slice(0, 200), csvPath }, - null, - 2 - ) - ) - } catch (e) { - fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) - } - app.quit() - return - } +// Claim the profile store before doing anything else. A second launch simply +// surfaces the window that already owns the database. +const isPrimaryInstance = app.requestSingleInstanceLock() +if (!isPrimaryInstance) { + app.quit() +} else { + app.on('second-instance', focusExistingWindow) - if (process.env.CWT_EDISC_TEST) { - const fs = await import('node:fs') - const { parseExportPackage, splitCopilotBody } = await import('./collectors/ediscoveryExport') - const out = join(process.env.TEMP || '.', 'cwt_edisc_out.txt') - function makeZip(name: string, content: string): Buffer { - const nameBuf = Buffer.from(name, 'utf8') - const data = Buffer.from(content, 'utf8') - const lfh = Buffer.alloc(30) - lfh.writeUInt32LE(0x04034b50, 0) - lfh.writeUInt16LE(20, 4) - lfh.writeUInt32LE(data.length, 18) - lfh.writeUInt32LE(data.length, 22) - lfh.writeUInt16LE(nameBuf.length, 26) - const localPart = Buffer.concat([lfh, nameBuf, data]) - const cdh = Buffer.alloc(46) - cdh.writeUInt32LE(0x02014b50, 0) - cdh.writeUInt32LE(data.length, 20) - cdh.writeUInt32LE(data.length, 24) - cdh.writeUInt16LE(nameBuf.length, 28) - cdh.writeUInt32LE(0, 42) - const cdPart = Buffer.concat([cdh, nameBuf]) - const eocd = Buffer.alloc(22) - eocd.writeUInt32LE(0x06054b50, 0) - eocd.writeUInt16LE(1, 8) - eocd.writeUInt16LE(1, 10) - eocd.writeUInt32LE(cdPart.length, 12) - eocd.writeUInt32LE(localPart.length, 16) - return Buffer.concat([localPart, cdPart, eocd]) - } - try { - const rec = { - id: 'i1', - conversationId: 'c1', - createdDateTime: '2026-06-01T10:00:00Z', - prompt: '계약서 요약해줘', - response: '요약 결과입니다.', - app: 'BizChat' - } - const zip = makeZip('items.json', JSON.stringify([rec])) - const rows = parseExportPackage(zip, 'user-1') - const split = splitCopilotBody('User: 안녕하세요\nCopilot: 반갑습니다') - fs.writeFileSync( - out, - JSON.stringify( - { - rowCount: rows.length, - rows: rows.map((r) => ({ type: r.interactionType, body: r.bodyText, session: r.sessionId, source: r.sourceType, req: r.requestId })), - split - }, - null, - 2 - ) - ) - } catch (e) { - fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) - } - app.quit() - return - } + app.whenReady().then(async () => { + registerHandlers() - if (process.env.CWT_DVPARSE_TEST) { - const fs = await import('node:fs') - const { parseConversationTranscript, parseEnvironmentsJson, parseFlowRunRecord } = await import('./collectors/dataverse') - const { analyzeAgent } = await import('./collectors/agentRisk') - const out = join(process.env.TEMP || '.', 'cwt_dvparse_out.txt') - try { - const content = JSON.stringify({ - activities: [ - { type: 'message', id: 'a1', from: { aadObjectId: 'aad-123', name: '홍길동' }, text: '안녕 에이전트', channelId: 'msteams', timestamp: 1780000000, conversation: { id: 'conv-1' } }, - { type: 'message', id: 'a2', from: { role: 0, name: 'Agent' }, recipient: { aadObjectId: 'aad-123' }, text: '안녕하세요!', channelId: 'msteams', timestamp: 1780000005 }, - { type: 'message', id: 'a3', from: { id: 'webuser' }, text: 'web only', channelId: 'webchat', timestamp: 1780000010 } - ] - }) - const all = parseConversationTranscript(content, { transcriptId: 't1', environmentId: 'env1', teamsOnly: false }) - const teams = parseConversationTranscript(content, { transcriptId: 't1', environmentId: 'env1', teamsOnly: true }) - const envs = parseEnvironmentsJson({ - value: [{ ApiUrl: 'https://contoso.crm.dynamics.com/api/data/v9.0/', Id: 'e1', FriendlyName: 'Contoso' }] - }) - const flow = parseFlowRunRecord( - { - flowrunid: 'run-1', - status: 'Failed', - starttime: '2026-06-20T01:00:00Z', - duration: '4200', - modernflowtype: 2, - _workflow_value: 'wf-1', - '_workflow_value@OData.Community.Display.V1.FormattedValue': '주문 처리 플로우', - _ownerid_value: 'owner-1', - '_ownerid_value@OData.Community.Display.V1.FormattedValue': '김철수', - createdon: '2026-06-20T01:00:05Z' - }, - 'env1', - 'Contoso' - ) - const risk = analyzeAgent([ - { componenttype: 5 }, - { componenttype: 1, data: 'httprequest connectorid foreach while invoketool' } - ]) - fs.writeFileSync( - out, - JSON.stringify( - { - allRows: all.rows.length, - allTypes: all.rows.map((r) => r.interactionType), - apps: all.rows.map((r) => r.app), - createdAts: all.rows.map((r) => r.createdAt), - participants: [...all.participants], - teamsRows: teams.rows.length, - teamsSkippedNonTeams: teams.skippedNonTeams, - envs, - flow, - risk: { - score: risk.score, - band: risk.band, - hasTrigger: risk.hasTrigger, - external: risk.externalCallCount, - tools: risk.toolCount, - loops: risk.loopCount - } - }, - null, - 2 - ) - ) - } catch (e) { - fs.writeFileSync(out, 'FAIL ' + (e instanceof Error ? e.stack : String(e))) + if (!app.isPackaged) { + const { runDevHarness } = await import('./devHarness') + if (await runDevHarness()) return } - app.quit() - return - } - createWindow() - schedulePurviewAttribution() - app.on('activate', () => { - if (BrowserWindow.getAllWindows().length === 0) createWindow() + createWindow() + schedulePurviewAttribution() + app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) createWindow() + }) }) -}) -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') app.quit() -}) + app.on('window-all-closed', () => { + if (process.platform !== 'darwin') app.quit() + }) -app.on('before-quit', () => { - if (purviewAttributionTimer) clearTimeout(purviewAttributionTimer) - purviewAttributionTimer = null -}) + app.on('before-quit', shutdownDb) +} diff --git a/src/main/onboard.ts b/src/main/onboard.ts index 114c33a..dd0da4a 100644 --- a/src/main/onboard.ts +++ b/src/main/onboard.ts @@ -13,6 +13,7 @@ import { hostname } from 'node:os' import { dirname } from 'node:path' import * as profiles from './profiles' import { persistTokenCache } from './tokenCache' +import { httpRequest } from './http' const BOOTSTRAP_CLIENT_ID = '14d82eec-204b-4c2f-b7e8-296a70dab67e' const GRAPH = 'https://graph.microsoft.com/v1.0' @@ -107,13 +108,15 @@ async function deviceLogin( } async function gpost(token: string, path: string, body: unknown): Promise> { - const res = await fetch(GRAPH + path, { + const res = await httpRequest(GRAPH + path, { method: 'POST', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) - if (!res.ok) throw new Error(`Graph POST ${path} ${res.status}: ${(await res.text()).slice(0, 300)}`) - return (await res.json()) as Record + if (!res.ok) throw new Error(`Graph POST ${path} ${res.status}: ${(await res.text().catch(() => '')).slice(0, 300)}`) + const text = await res.text() + if (!text.trim()) return {} + return JSON.parse(text) as Record } async function registerApp( @@ -188,7 +191,7 @@ async function verifyRedirectUri( const deadline = Date.now() + timeoutMs for (;;) { try { - const res = await fetch(`${GRAPH}/applications/${appObjectId}?$select=web`, { + const res = await httpRequest(`${GRAPH}/applications/${appObjectId}?$select=web`, { headers: { Authorization: `Bearer ${token}` } }) if (res.ok) { diff --git a/src/main/portal.ts b/src/main/portal.ts index ce97ec6..9794c44 100644 --- a/src/main/portal.ts +++ b/src/main/portal.ts @@ -10,6 +10,8 @@ import { readFileSync, rmSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { randomUUID } from 'node:crypto' +import { httpRequest } from './http' +import { hardenPortalWindow } from './windowSecurity' export interface CaptureOptions { /** URL to load (e.g. the PPAC capacity page). */ @@ -53,6 +55,7 @@ export function captureBearerToken(opts: CaptureOptions): Promise { sandbox: true } }) + hardenPortalWindow(win, opts.onLog) function reveal(reason: string): void { if (shown || settled || win.isDestroyed()) return @@ -272,6 +275,7 @@ export function downloadViaBrowser( autoHideMenuBar: true, webPreferences: { partition, nodeIntegration: false, contextIsolation: true, sandbox: true } }) + hardenPortalWindow(win, opts.onLog) function reveal(reason: string): void { if (shown || settled || win.isDestroyed()) return @@ -469,6 +473,7 @@ export function capturePortalTokens(opts: { autoHideMenuBar: true, webPreferences: { partition, nodeIntegration: false, contextIsolation: true, sandbox: true } }) + hardenPortalWindow(win, opts.onLog) ses.webRequest.onBeforeSendHeaders(filter, (details, callback) => { const headers = details.requestHeaders @@ -673,6 +678,7 @@ export function captureDataverseTokens(opts: DataverseCaptureOptions): Promise

{ let body = '' try { - const r = await fetch(BAP_ENVIRONMENTS_URL, { headers: { Authorization: `Bearer ${bap}` } }) + const r = await httpRequest(BAP_ENVIRONMENTS_URL, { headers: { Authorization: `Bearer ${bap}` } }) if (!r.ok) { opts.onLog?.(`환경 목록 조회 실패: HTTP ${r.status}`) return [] @@ -894,7 +900,7 @@ export function captureDataverseTokens(opts: DataverseCaptureOptions): Promise

{ try { - const r = await fetch( + const r = await httpRequest( `https://${orgHost}/api/data/v9.2/conversationtranscripts?$top=1&$select=conversationtranscriptid`, { headers: { diff --git a/src/main/windowSecurity.ts b/src/main/windowSecurity.ts index 8bdc523..812df6b 100644 --- a/src/main/windowSecurity.ts +++ b/src/main/windowSecurity.ts @@ -1,7 +1,39 @@ +import type { BrowserWindow } from 'electron' + +/** + * Hosts the app is allowed to hand to the OS browser. The renderer only ever + * links to Microsoft documentation and admin portals, so anything else is a + * navigation the app did not intend — refuse it rather than launching it. + */ +const EXTERNAL_HOST_SUFFIXES = [ + 'microsoft.com', + 'microsoftonline.com', + 'microsoft.net', + 'azure.com', + 'office.com', + 'office.net', + 'sharepoint.com', + 'dynamics.com', + 'powerapps.com', + 'powerautomate.com', + 'powerplatform.com', + 'msftauth.net', + 'live.com', + 'windows.net', + 'github.com' +] + +function hostAllowed(host: string): boolean { + const h = host.toLowerCase() + return EXTERNAL_HOST_SUFFIXES.some((suffix) => h === suffix || h.endsWith(`.${suffix}`)) +} + export function isSafeExternalUrl(value: string): boolean { try { const url = new URL(value) - return url.protocol === 'https:' && !url.username && !url.password + if (url.protocol !== 'https:') return false + if (url.username || url.password) return false + return hostAllowed(url.hostname) } catch { return false } @@ -21,4 +53,57 @@ export function isAllowedPrimaryNavigation(target: string, rendererEntry: string } catch { return false } -} \ No newline at end of file +} + +/** Web content is only ever legitimate over http(s) in an interactive portal window. */ +export function isWebScheme(value: string): boolean { + try { + const protocol = new URL(value).protocol + return protocol === 'https:' || protocol === 'http:' + } catch { + return false + } +} + +/** + * Harden an interactive sign-in / portal window. + * + * These windows navigate freely across Microsoft and customer-federated identity + * providers, so an origin allowlist would break federated tenants. What they must + * never do is leave the web: a `file:` or custom-scheme navigation inside the + * authenticated session partition, an unmanaged child window that silently + * inherits that partition, or an attached , are all avoidable risks. + */ +export function hardenPortalWindow(win: BrowserWindow, onLog?: (line: string) => void): void { + const contents = win.webContents + contents.setWindowOpenHandler(({ url }) => { + if (!isWebScheme(url)) { + onLog?.(`차단된 팝업(비 웹 스킴): ${url.slice(0, 120)}`) + return { action: 'deny' } + } + // Auth flows do use popups; allow them but force the same safe preferences + // instead of letting the child inherit whatever the opener asked for. + return { + action: 'allow', + overrideBrowserWindowOptions: { + autoHideMenuBar: true, + webPreferences: { + nodeIntegration: false, + contextIsolation: true, + sandbox: true, + webviewTag: false + } + } + } + }) + contents.on('will-navigate', (event, url) => { + if (!isWebScheme(url)) { + event.preventDefault() + onLog?.(`차단된 이동(비 웹 스킴): ${url.slice(0, 120)}`) + } + }) + contents.on('will-attach-webview', (event) => { + event.preventDefault() + onLog?.('차단된 부착 시도') + }) +} diff --git a/src/renderer/index.html b/src/renderer/index.html index 68fc312..8767f5c 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -2,7 +2,7 @@ - + CopilotWatchTower diff --git a/src/renderer/src/i18n/index.ts b/src/renderer/src/i18n/index.ts index 5b92877..ed5263d 100644 --- a/src/renderer/src/i18n/index.ts +++ b/src/renderer/src/i18n/index.ts @@ -62,4 +62,12 @@ void i18n.use(initReactI18next).init({ returnNull: false }) +// Keep in sync so screen readers, hyphenation and `:lang()` rules +// follow the selected language instead of the hardcoded `ko` in index.html. +function syncDocumentLanguage(lng: string): void { + if (typeof document !== 'undefined') document.documentElement.lang = lng +} +syncDocumentLanguage(i18n.language) +i18n.on('languageChanged', syncDocumentLanguage) + export default i18n diff --git a/src/renderer/src/i18n/locales/en/auditCollect.json b/src/renderer/src/i18n/locales/en/auditCollect.json index 3e9ab5d..2d20cb6 100644 --- a/src/renderer/src/i18n/locales/en/auditCollect.json +++ b/src/renderer/src/i18n/locales/en/auditCollect.json @@ -1,16 +1,43 @@ { "collectStart": "Start collection", - "kpis": { "total": "Total audit events", "purview": "Purview", "purviewFoot": "Unified audit", "entraAudit": "Entra audit", "entraAuditFoot": "Directory", "entraSignin": "Entra sign-in" }, + "kpis": { + "total": "Total audit events", + "purview": "Purview", + "purviewFoot": "Unified audit", + "entraAudit": "Entra audit", + "entraAuditFoot": "Directory", + "entraSignin": "Entra sign-in" + }, + "sourceLabel": { + "purview": "Purview unified audit", + "entra_audit": "Entra directory audit", + "entra_signin": "Entra sign-in" + }, "sourceStatus": { "title": "Collection source status", "count_other": "{{count}} sources", - "columns": { "source": "Source", "status": "Status", "last": "Last collected", "count": "Count" }, - "status": { "error": "Error", "processing": "Processing", "active": "Active", "inactive": "Inactive" } + "columns": { + "source": "Source", + "status": "Status", + "last": "Last collected", + "count": "Count" + }, + "status": { + "error": "Error", + "processing": "Processing", + "active": "Active", + "inactive": "Inactive" + } }, "recent": { "title": "Recent audit events", "subtitle_other": "Latest {{count}}", - "columns": { "time": "Time", "source": "Source", "operation": "Operation", "actor": "Actor" }, + "columns": { + "time": "Time", + "source": "Source", + "operation": "Operation", + "actor": "Actor" + }, "empty": "No audit events collected yet. Click Start collection." } } diff --git a/src/renderer/src/i18n/locales/en/conversations.json b/src/renderer/src/i18n/locales/en/conversations.json index 2558041..c36e296 100644 --- a/src/renderer/src/i18n/locales/en/conversations.json +++ b/src/renderer/src/i18n/locales/en/conversations.json @@ -1,5 +1,9 @@ { - "scope": { "all": "All", "title": "Title", "body": "Body" }, + "scope": { + "all": "All", + "title": "Title", + "body": "Body" + }, "searchPlaceholder": { "title": "Search conversation titles", "body": "Search conversation body", @@ -40,8 +44,18 @@ "backToAgents": "Back to agents", "unknown": "Unknown user" }, - "panels": { "conversations": "Conversations", "collapseAgents": "Collapse agent panel", "expandAgents": "Expand agent panel", "collapseUsers": "Collapse user panel", "expandUsers": "Expand user panel" }, - "pagination": { "previous": "Previous page", "next": "Next page", "status": "{{page}} / {{pages}} · {{total}}" }, + "panels": { + "conversations": "Conversations", + "collapseAgents": "Collapse agent panel", + "expandAgents": "Expand agent panel", + "collapseUsers": "Collapse user panel", + "expandUsers": "Expand user panel" + }, + "pagination": { + "previous": "Previous page", + "next": "Next page", + "status": "{{page}} / {{pages}} · {{total}}" + }, "count_other": "{{count}} conversations", "count_one": "{{count}} conversation", "noMatch": "No matching conversations.", @@ -49,5 +63,10 @@ "messageCount_one": "{{count}} message", "noMessages": "No messages to display.", "rawInteractionTitle": "Raw interaction JSON", - "empty": { "title": "Select a conversation", "desc": "Select a conversation from the list on the left to see the full messages here." } + "empty": { + "title": "Select a conversation", + "desc": "Select a conversation from the list on the left to see the full messages here." + }, + "threadUnavailable": "This conversation has no stored interaction id, so its turns cannot be loaded.", + "threadLoadFailed": "Failed to load conversation: {{message}}" } diff --git a/src/renderer/src/i18n/locales/en/security.json b/src/renderer/src/i18n/locales/en/security.json index 3459cdd..c933dff 100644 --- a/src/renderer/src/i18n/locales/en/security.json +++ b/src/renderer/src/i18n/locales/en/security.json @@ -5,8 +5,16 @@ "entra_audit": "Entra directory audit", "entra_signin": "Entra sign-in" }, - "filters": { "sourceFilter": "Source filter", "dateFrom": "Start date", "dateTo": "End date", "searchPlaceholder": "Search operation/user/app", "apply": "Apply", "reset": "Reset" }, + "filters": { + "sourceFilter": "Source filter", + "dateFrom": "Start date", + "dateTo": "End date", + "searchPlaceholder": "Search operation/user/app", + "apply": "Apply", + "reset": "Reset" + }, "count_other": "{{count}}", + "truncated": "showing {{shown}} of {{total}}", "kpis": { "total": "Audit events", "totalFoot": "Filtered results", @@ -36,5 +44,8 @@ "result": "Result" }, "rawAuditEventTitle": "Raw audit event", - "auditEvents": { "title": "Audit events", "subtitle_other": "{{count}} · Latest first" } + "auditEvents": { + "title": "Audit events", + "subtitle_other": "{{count}} · Latest first" + } } diff --git a/src/renderer/src/i18n/locales/es/auditCollect.json b/src/renderer/src/i18n/locales/es/auditCollect.json index 5207a0f..d866d73 100644 --- a/src/renderer/src/i18n/locales/es/auditCollect.json +++ b/src/renderer/src/i18n/locales/es/auditCollect.json @@ -1,16 +1,43 @@ { "collectStart": "Iniciar recopilación", - "kpis": { "total": "Total de eventos de auditoría", "purview": "Purview", "purviewFoot": "Auditoría unificada", "entraAudit": "Auditoría de Entra", "entraAuditFoot": "Directorio", "entraSignin": "Inicio de sesión de Entra" }, + "kpis": { + "total": "Total de eventos de auditoría", + "purview": "Purview", + "purviewFoot": "Auditoría unificada", + "entraAudit": "Auditoría de Entra", + "entraAuditFoot": "Directorio", + "entraSignin": "Inicio de sesión de Entra" + }, + "sourceLabel": { + "purview": "Auditoría unificada de Purview", + "entra_audit": "Auditoría de directorio de Entra", + "entra_signin": "Inicio de sesión de Entra" + }, "sourceStatus": { "title": "Estado de las fuentes de recopilación", "count_other": "{{count}} fuentes", - "columns": { "source": "Fuente", "status": "Estado", "last": "Última recopilación", "count": "Cantidad" }, - "status": { "error": "Error", "processing": "Procesando", "active": "Activo", "inactive": "Inactivo" } + "columns": { + "source": "Fuente", + "status": "Estado", + "last": "Última recopilación", + "count": "Cantidad" + }, + "status": { + "error": "Error", + "processing": "Procesando", + "active": "Activo", + "inactive": "Inactivo" + } }, "recent": { "title": "Eventos de auditoría recientes", "subtitle_other": "Últimos {{count}}", - "columns": { "time": "Hora", "source": "Fuente", "operation": "Operación", "actor": "Actor" }, + "columns": { + "time": "Hora", + "source": "Fuente", + "operation": "Operación", + "actor": "Actor" + }, "empty": "Aún no se han recopilado eventos de auditoría. Haga clic en Iniciar recopilación." } } diff --git a/src/renderer/src/i18n/locales/es/conversations.json b/src/renderer/src/i18n/locales/es/conversations.json index 418973f..f0cbdcd 100644 --- a/src/renderer/src/i18n/locales/es/conversations.json +++ b/src/renderer/src/i18n/locales/es/conversations.json @@ -1,5 +1,9 @@ { - "scope": { "all": "Todo", "title": "Título", "body": "Cuerpo" }, + "scope": { + "all": "Todo", + "title": "Título", + "body": "Cuerpo" + }, "searchPlaceholder": { "title": "Buscar títulos de conversación", "body": "Buscar cuerpo de conversación", @@ -40,8 +44,18 @@ "backToAgents": "Volver a los agentes", "unknown": "Usuario desconocido" }, - "panels": { "conversations": "Conversaciones", "collapseAgents": "Contraer panel de agentes", "expandAgents": "Expandir panel de agentes", "collapseUsers": "Contraer panel de usuarios", "expandUsers": "Expandir panel de usuarios" }, - "pagination": { "previous": "Página anterior", "next": "Página siguiente", "status": "{{page}} / {{pages}} · {{total}}" }, + "panels": { + "conversations": "Conversaciones", + "collapseAgents": "Contraer panel de agentes", + "expandAgents": "Expandir panel de agentes", + "collapseUsers": "Contraer panel de usuarios", + "expandUsers": "Expandir panel de usuarios" + }, + "pagination": { + "previous": "Página anterior", + "next": "Página siguiente", + "status": "{{page}} / {{pages}} · {{total}}" + }, "count_other": "{{count}} conversaciones", "count_one": "{{count}} conversación", "noMatch": "No hay conversaciones coincidentes.", @@ -49,5 +63,10 @@ "messageCount_one": "{{count}} mensaje", "noMessages": "No hay mensajes para mostrar.", "rawInteractionTitle": "JSON de interacción sin procesar", - "empty": { "title": "Seleccione una conversación", "desc": "Seleccione una conversación de la lista de la izquierda para ver todos los mensajes aquí." } + "empty": { + "title": "Seleccione una conversación", + "desc": "Seleccione una conversación de la lista de la izquierda para ver todos los mensajes aquí." + }, + "threadUnavailable": "Esta conversación no tiene un id de interacción almacenado, por lo que no se pueden cargar sus turnos.", + "threadLoadFailed": "No se pudo cargar la conversación: {{message}}" } diff --git a/src/renderer/src/i18n/locales/es/security.json b/src/renderer/src/i18n/locales/es/security.json index e180333..fc75313 100644 --- a/src/renderer/src/i18n/locales/es/security.json +++ b/src/renderer/src/i18n/locales/es/security.json @@ -5,8 +5,16 @@ "entra_audit": "Auditoría de directorio de Entra", "entra_signin": "Inicio de sesión de Entra" }, - "filters": { "sourceFilter": "Filtro de fuente", "dateFrom": "Fecha de inicio", "dateTo": "Fecha de fin", "searchPlaceholder": "Buscar operación/usuario/app", "apply": "Aplicar", "reset": "Restablecer" }, + "filters": { + "sourceFilter": "Filtro de fuente", + "dateFrom": "Fecha de inicio", + "dateTo": "Fecha de fin", + "searchPlaceholder": "Buscar operación/usuario/app", + "apply": "Aplicar", + "reset": "Restablecer" + }, "count_other": "{{count}}", + "truncated": "mostrando {{shown}} de {{total}}", "kpis": { "total": "Eventos de auditoría", "totalFoot": "Resultados filtrados", @@ -36,5 +44,8 @@ "result": "Resultado" }, "rawAuditEventTitle": "Evento de auditoría sin procesar", - "auditEvents": { "title": "Eventos de auditoría", "subtitle_other": "{{count}} · Más reciente primero" } + "auditEvents": { + "title": "Eventos de auditoría", + "subtitle_other": "{{count}} · Más reciente primero" + } } diff --git a/src/renderer/src/i18n/locales/ja/auditCollect.json b/src/renderer/src/i18n/locales/ja/auditCollect.json index fb3b77a..ed623ff 100644 --- a/src/renderer/src/i18n/locales/ja/auditCollect.json +++ b/src/renderer/src/i18n/locales/ja/auditCollect.json @@ -1,16 +1,43 @@ { "collectStart": "収集開始", - "kpis": { "total": "総監査イベント", "purview": "Purview", "purviewFoot": "統合監査", "entraAudit": "Entra監査", "entraAuditFoot": "ディレクトリ", "entraSignin": "Entraサインイン" }, + "kpis": { + "total": "総監査イベント", + "purview": "Purview", + "purviewFoot": "統合監査", + "entraAudit": "Entra監査", + "entraAuditFoot": "ディレクトリ", + "entraSignin": "Entraサインイン" + }, + "sourceLabel": { + "purview": "Purview 統合監査", + "entra_audit": "Entra ディレクトリ監査", + "entra_signin": "Entra サインイン" + }, "sourceStatus": { "title": "収集ソース状態", "count_other": "{{count}}件のソース", - "columns": { "source": "ソース", "status": "状態", "last": "最終収集", "count": "件数" }, - "status": { "error": "エラー", "processing": "処理中", "active": "有効", "inactive": "無効" } + "columns": { + "source": "ソース", + "status": "状態", + "last": "最終収集", + "count": "件数" + }, + "status": { + "error": "エラー", + "processing": "処理中", + "active": "有効", + "inactive": "無効" + } }, "recent": { "title": "最近の監査イベント", "subtitle_other": "最新{{count}}件", - "columns": { "time": "時刻", "source": "ソース", "operation": "操作", "actor": "行為者" }, + "columns": { + "time": "時刻", + "source": "ソース", + "operation": "操作", + "actor": "行為者" + }, "empty": "まだ収集された監査イベントがありません。収集開始を押してください。" } } diff --git a/src/renderer/src/i18n/locales/ja/conversations.json b/src/renderer/src/i18n/locales/ja/conversations.json index 1c77aae..4c77889 100644 --- a/src/renderer/src/i18n/locales/ja/conversations.json +++ b/src/renderer/src/i18n/locales/ja/conversations.json @@ -1,5 +1,9 @@ { - "scope": { "all": "すべて", "title": "タイトル", "body": "本文" }, + "scope": { + "all": "すべて", + "title": "タイトル", + "body": "本文" + }, "searchPlaceholder": { "title": "会話タイトルを検索", "body": "会話本文を検索", @@ -40,12 +44,27 @@ "backToAgents": "エージェント一覧へ戻る", "unknown": "不明なユーザー" }, - "panels": { "conversations": "会話", "collapseAgents": "エージェントパネルを折りたたむ", "expandAgents": "エージェントパネルを展開", "collapseUsers": "ユーザーパネルを折りたたむ", "expandUsers": "ユーザーパネルを展開" }, - "pagination": { "previous": "前のページ", "next": "次のページ", "status": "{{page}} / {{pages}} · {{total}}件" }, + "panels": { + "conversations": "会話", + "collapseAgents": "エージェントパネルを折りたたむ", + "expandAgents": "エージェントパネルを展開", + "collapseUsers": "ユーザーパネルを折りたたむ", + "expandUsers": "ユーザーパネルを展開" + }, + "pagination": { + "previous": "前のページ", + "next": "次のページ", + "status": "{{page}} / {{pages}} · {{total}}件" + }, "count_other": "{{count}}件の会話", "noMatch": "一致する会話がありません。", "messageCount_other": "{{count}}件のメッセージ", "noMessages": "表示するメッセージがありません。", "rawInteractionTitle": "生のインタラクションJSON", - "empty": { "title": "会話を選択してください", "desc": "左側のリストから会話を選択すると、すべてのメッセージがここに表示されます。" } + "empty": { + "title": "会話を選択してください", + "desc": "左側のリストから会話を選択すると、すべてのメッセージがここに表示されます。" + }, + "threadUnavailable": "この会話には保存された対話IDがないため、本文を読み込めません。", + "threadLoadFailed": "会話の読み込みに失敗しました: {{message}}" } diff --git a/src/renderer/src/i18n/locales/ja/security.json b/src/renderer/src/i18n/locales/ja/security.json index 4ab4aef..79ee107 100644 --- a/src/renderer/src/i18n/locales/ja/security.json +++ b/src/renderer/src/i18n/locales/ja/security.json @@ -5,8 +5,16 @@ "entra_audit": "Entraディレクトリ監査", "entra_signin": "Entraサインイン" }, - "filters": { "sourceFilter": "ソースフィルター", "dateFrom": "開始日", "dateTo": "終了日", "searchPlaceholder": "操作・ユーザー・アプリを検索", "apply": "適用", "reset": "リセット" }, + "filters": { + "sourceFilter": "ソースフィルター", + "dateFrom": "開始日", + "dateTo": "終了日", + "searchPlaceholder": "操作・ユーザー・アプリを検索", + "apply": "適用", + "reset": "リセット" + }, "count_other": "{{count}}件", + "truncated": "全 {{total}} 件中 {{shown}} 件を表示", "kpis": { "total": "監査イベント", "totalFoot": "フィルター結果", @@ -36,5 +44,8 @@ "result": "結果" }, "rawAuditEventTitle": "監査イベントの生データ", - "auditEvents": { "title": "監査イベント", "subtitle_other": "{{count}}件 · 新しい順" } + "auditEvents": { + "title": "監査イベント", + "subtitle_other": "{{count}}件 · 新しい順" + } } diff --git a/src/renderer/src/i18n/locales/ko/auditCollect.json b/src/renderer/src/i18n/locales/ko/auditCollect.json index 620e0f8..35be14f 100644 --- a/src/renderer/src/i18n/locales/ko/auditCollect.json +++ b/src/renderer/src/i18n/locales/ko/auditCollect.json @@ -1,16 +1,43 @@ { "collectStart": "수집 시작", - "kpis": { "total": "총 감사 이벤트", "purview": "Purview", "purviewFoot": "통합 감사", "entraAudit": "Entra 감사", "entraAuditFoot": "디렉터리", "entraSignin": "Entra 로그인" }, + "kpis": { + "total": "총 감사 이벤트", + "purview": "Purview", + "purviewFoot": "통합 감사", + "entraAudit": "Entra 감사", + "entraAuditFoot": "디렉터리", + "entraSignin": "Entra 로그인" + }, + "sourceLabel": { + "purview": "Purview 통합 감사", + "entra_audit": "Entra 디렉터리 감사", + "entra_signin": "Entra 로그인" + }, "sourceStatus": { "title": "수집 소스 상태", "count_other": "{{count}}개 소스", - "columns": { "source": "소스", "status": "상태", "last": "마지막 수집", "count": "건수" }, - "status": { "error": "오류", "processing": "처리 중", "active": "활성", "inactive": "비활성" } + "columns": { + "source": "소스", + "status": "상태", + "last": "마지막 수집", + "count": "건수" + }, + "status": { + "error": "오류", + "processing": "처리 중", + "active": "활성", + "inactive": "비활성" + } }, "recent": { "title": "최근 감사 이벤트", "subtitle_other": "최신 {{count}}건", - "columns": { "time": "시각", "source": "소스", "operation": "작업", "actor": "행위자" }, + "columns": { + "time": "시각", + "source": "소스", + "operation": "작업", + "actor": "행위자" + }, "empty": "아직 수집된 감사 이벤트가 없습니다. 수집 시작을 눌러주세요." } } diff --git a/src/renderer/src/i18n/locales/ko/conversations.json b/src/renderer/src/i18n/locales/ko/conversations.json index 6e08753..4c93da5 100644 --- a/src/renderer/src/i18n/locales/ko/conversations.json +++ b/src/renderer/src/i18n/locales/ko/conversations.json @@ -1,5 +1,9 @@ { - "scope": { "all": "전체", "title": "제목", "body": "본문" }, + "scope": { + "all": "전체", + "title": "제목", + "body": "본문" + }, "searchPlaceholder": { "title": "대화 제목 검색", "body": "대화 본문 검색", @@ -40,12 +44,27 @@ "backToAgents": "에이전트 목록으로", "unknown": "알 수 없는 사용자" }, - "panels": { "conversations": "대화", "collapseAgents": "에이전트 패널 접기", "expandAgents": "에이전트 패널 펼치기", "collapseUsers": "사용자 패널 접기", "expandUsers": "사용자 패널 펼치기" }, - "pagination": { "previous": "이전 페이지", "next": "다음 페이지", "status": "{{page}} / {{pages}} · {{total}}개" }, + "panels": { + "conversations": "대화", + "collapseAgents": "에이전트 패널 접기", + "expandAgents": "에이전트 패널 펼치기", + "collapseUsers": "사용자 패널 접기", + "expandUsers": "사용자 패널 펼치기" + }, + "pagination": { + "previous": "이전 페이지", + "next": "다음 페이지", + "status": "{{page}} / {{pages}} · {{total}}개" + }, "count_other": "{{count}}개 대화", "noMatch": "일치하는 대화가 없습니다.", "messageCount_other": "{{count}}개 메시지", "noMessages": "표시할 메시지가 없습니다.", "rawInteractionTitle": "원본 상호작용 JSON", - "empty": { "title": "대화를 선택하세요", "desc": "왼쪽 목록에서 대화를 선택하면 전체 메시지가 여기에 표시됩니다." } + "empty": { + "title": "대화를 선택하세요", + "desc": "왼쪽 목록에서 대화를 선택하면 전체 메시지가 여기에 표시됩니다." + }, + "threadUnavailable": "이 대화에는 저장된 상호작용 ID가 없어 본문을 불러올 수 없습니다.", + "threadLoadFailed": "대화를 불러오지 못했습니다: {{message}}" } diff --git a/src/renderer/src/i18n/locales/ko/security.json b/src/renderer/src/i18n/locales/ko/security.json index 6cd56d0..8198366 100644 --- a/src/renderer/src/i18n/locales/ko/security.json +++ b/src/renderer/src/i18n/locales/ko/security.json @@ -5,8 +5,16 @@ "entra_audit": "Entra 디렉터리 감사", "entra_signin": "Entra 로그인" }, - "filters": { "sourceFilter": "소스 필터", "dateFrom": "시작일", "dateTo": "종료일", "searchPlaceholder": "작업 · 사용자 · 앱 검색", "apply": "적용", "reset": "초기화" }, + "filters": { + "sourceFilter": "소스 필터", + "dateFrom": "시작일", + "dateTo": "종료일", + "searchPlaceholder": "작업 · 사용자 · 앱 검색", + "apply": "적용", + "reset": "초기화" + }, "count_other": "{{count}}건", + "truncated": "전체 {{total}}건 중 {{shown}}건 표시", "kpis": { "total": "감사 이벤트", "totalFoot": "필터 결과", @@ -36,5 +44,8 @@ "result": "결과" }, "rawAuditEventTitle": "감사 이벤트 원본", - "auditEvents": { "title": "감사 이벤트", "subtitle_other": "{{count}}건 · 최신순" } + "auditEvents": { + "title": "감사 이벤트", + "subtitle_other": "{{count}}건 · 최신순" + } } diff --git a/src/renderer/src/i18n/locales/zh-CN/auditCollect.json b/src/renderer/src/i18n/locales/zh-CN/auditCollect.json index b7de2b8..ce56774 100644 --- a/src/renderer/src/i18n/locales/zh-CN/auditCollect.json +++ b/src/renderer/src/i18n/locales/zh-CN/auditCollect.json @@ -1,16 +1,43 @@ { "collectStart": "开始收集", - "kpis": { "total": "总审计事件", "purview": "Purview", "purviewFoot": "统一审计", "entraAudit": "Entra 审计", "entraAuditFoot": "目录", "entraSignin": "Entra 登录" }, + "kpis": { + "total": "总审计事件", + "purview": "Purview", + "purviewFoot": "统一审计", + "entraAudit": "Entra 审计", + "entraAuditFoot": "目录", + "entraSignin": "Entra 登录" + }, + "sourceLabel": { + "purview": "Purview 统一审核", + "entra_audit": "Entra 目录审核", + "entra_signin": "Entra 登录" + }, "sourceStatus": { "title": "收集来源状态", "count_other": "{{count}} 个来源", - "columns": { "source": "来源", "status": "状态", "last": "最后收集", "count": "数量" }, - "status": { "error": "错误", "processing": "处理中", "active": "活跃", "inactive": "不活跃" } + "columns": { + "source": "来源", + "status": "状态", + "last": "最后收集", + "count": "数量" + }, + "status": { + "error": "错误", + "processing": "处理中", + "active": "活跃", + "inactive": "不活跃" + } }, "recent": { "title": "最近的审计事件", "subtitle_other": "最新 {{count}} 条", - "columns": { "time": "时间", "source": "来源", "operation": "操作", "actor": "操作者" }, + "columns": { + "time": "时间", + "source": "来源", + "operation": "操作", + "actor": "操作者" + }, "empty": "尚未收集到审计事件。请点击开始收集。" } } diff --git a/src/renderer/src/i18n/locales/zh-CN/conversations.json b/src/renderer/src/i18n/locales/zh-CN/conversations.json index e2ca372..f5bd240 100644 --- a/src/renderer/src/i18n/locales/zh-CN/conversations.json +++ b/src/renderer/src/i18n/locales/zh-CN/conversations.json @@ -1,5 +1,9 @@ { - "scope": { "all": "全部", "title": "标题", "body": "正文" }, + "scope": { + "all": "全部", + "title": "标题", + "body": "正文" + }, "searchPlaceholder": { "title": "搜索对话标题", "body": "搜索对话正文", @@ -40,12 +44,27 @@ "backToAgents": "返回智能体列表", "unknown": "未知用户" }, - "panels": { "conversations": "对话", "collapseAgents": "折叠智能体面板", "expandAgents": "展开智能体面板", "collapseUsers": "折叠用户面板", "expandUsers": "展开用户面板" }, - "pagination": { "previous": "上一页", "next": "下一页", "status": "{{page}} / {{pages}} · {{total}} 条" }, + "panels": { + "conversations": "对话", + "collapseAgents": "折叠智能体面板", + "expandAgents": "展开智能体面板", + "collapseUsers": "折叠用户面板", + "expandUsers": "展开用户面板" + }, + "pagination": { + "previous": "上一页", + "next": "下一页", + "status": "{{page}} / {{pages}} · {{total}} 条" + }, "count_other": "{{count}} 个对话", "noMatch": "没有匹配的对话。", "messageCount_other": "{{count}} 条消息", "noMessages": "没有可显示的消息。", "rawInteractionTitle": "原始交互 JSON", - "empty": { "title": "请选择一个对话", "desc": "从左侧列表中选择一个对话,即可在此处查看完整消息。" } + "empty": { + "title": "请选择一个对话", + "desc": "从左侧列表中选择一个对话,即可在此处查看完整消息。" + }, + "threadUnavailable": "该会话没有存储的交互 ID,无法加载对话内容。", + "threadLoadFailed": "加载会话失败:{{message}}" } diff --git a/src/renderer/src/i18n/locales/zh-CN/security.json b/src/renderer/src/i18n/locales/zh-CN/security.json index 2c57b4b..6cd5407 100644 --- a/src/renderer/src/i18n/locales/zh-CN/security.json +++ b/src/renderer/src/i18n/locales/zh-CN/security.json @@ -5,8 +5,16 @@ "entra_audit": "Entra 目录审计", "entra_signin": "Entra 登录" }, - "filters": { "sourceFilter": "来源筛选", "dateFrom": "开始日期", "dateTo": "结束日期", "searchPlaceholder": "搜索操作 · 用户 · 应用", "apply": "应用", "reset": "重置" }, + "filters": { + "sourceFilter": "来源筛选", + "dateFrom": "开始日期", + "dateTo": "结束日期", + "searchPlaceholder": "搜索操作 · 用户 · 应用", + "apply": "应用", + "reset": "重置" + }, "count_other": "{{count}} 条", + "truncated": "共 {{total}} 条,显示 {{shown}} 条", "kpis": { "total": "审计事件", "totalFoot": "筛选结果", @@ -36,5 +44,8 @@ "result": "结果" }, "rawAuditEventTitle": "原始审计事件", - "auditEvents": { "title": "审计事件", "subtitle_other": "{{count}} 条 · 最新在前" } + "auditEvents": { + "title": "审计事件", + "subtitle_other": "{{count}} 条 · 最新在前" + } } diff --git a/src/renderer/src/pages/Alerts.tsx b/src/renderer/src/pages/Alerts.tsx index 333d415..b32ce8d 100644 --- a/src/renderer/src/pages/Alerts.tsx +++ b/src/renderer/src/pages/Alerts.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react' import { Loader2, Play } from 'lucide-react' import { useTranslation } from 'react-i18next' import { invoke } from '../lib/api' +import { useNumberFormat } from '../lib/format' interface Rule { name: string @@ -39,12 +40,10 @@ const RULE_LABEL_KEYS = [ 'high_risk_agent' ] as const -function n(v: number | null): string { - return (v ?? 0).toLocaleString('ko-KR', { maximumFractionDigits: 2 }) -} - export function Alerts(): JSX.Element { const { t } = useTranslation('alerts') + const fmt = useNumberFormat() + const n = (v: number | null): string => fmt(v ?? 0, { maximumFractionDigits: 2 }) const RULE_LABEL: Record = Object.fromEntries( RULE_LABEL_KEYS.map((k) => [k, t(`ruleLabel.${k}`)]) ) diff --git a/src/renderer/src/pages/AuditCollect.tsx b/src/renderer/src/pages/AuditCollect.tsx index add8cdc..b15663b 100644 --- a/src/renderer/src/pages/AuditCollect.tsx +++ b/src/renderer/src/pages/AuditCollect.tsx @@ -31,17 +31,13 @@ interface DTO { const FALLBACK: DTO = { kpis: { total: 0, purview: 0, entraAudit: 0, entraSignin: 0 }, sources: [ - { source: 'purview', label: 'Purview 통합 감사', enabled: true, pending: false, last: '—', count: 0, error: null }, - { source: 'entra_audit', label: 'Entra 디렉터리 감사', enabled: true, pending: false, last: '—', count: 0, error: null }, - { source: 'entra_signin', label: 'Entra 로그인', enabled: true, pending: false, last: '—', count: 0, error: null } + { source: 'purview', label: '', enabled: true, pending: false, last: '—', count: 0, error: null }, + { source: 'entra_audit', label: '', enabled: true, pending: false, last: '—', count: 0, error: null }, + { source: 'entra_signin', label: '', enabled: true, pending: false, last: '—', count: 0, error: null } ], recent: [] } -function n(v: number): string { - return v.toLocaleString('ko-KR') -} - export function AuditCollect(): JSX.Element { const { t } = useTranslation('auditCollect') const n = useNumberFormat() @@ -104,7 +100,7 @@ export function AuditCollect(): JSX.Element { {d.sources.map((s) => ( - {s.label} + {s.label || t(`sourceLabel.${s.source}`, { defaultValue: s.source })} {s.pending diff --git a/src/renderer/src/pages/Conversations.tsx b/src/renderer/src/pages/Conversations.tsx index 3b1ac81..90f905b 100644 --- a/src/renderer/src/pages/Conversations.tsx +++ b/src/renderer/src/pages/Conversations.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from 'react' +import { useEffect, useState, useMemo } from 'react' import { Bot, ChevronLeft, @@ -81,73 +81,6 @@ function isTechnicalAgentName(name: string, id?: string): boolean { ) } -const THREADS: Record = { - '밀라노 쇼핑 일정 짜줘': [ - { role: 'user', text: '밀라노 2박 3일 쇼핑 위주 일정 짜줘. 명품 아울렛도 포함했으면 좋겠어.' }, - { - role: 'bot', - text: - '밀라노 2박 3일 쇼핑 일정입니다.\n\n1일차: 몬테나폴레오네 거리(명품 부티크) → 두오모 → 갤러리아\n2일차: 세라발레 디자이너 아울렛(당일 왕복)\n3일차: 코르소 부에노스아이레스(중저가) → 출국\n\n각 일정에 이동 수단과 예상 소요 시간을 더 넣어드릴까요?' - }, - { role: 'user', text: '둘째 날 아울렛 가는 교통편이랑 소요시간 알려줘.' }, - { - role: 'bot', - text: - '세라발레 아울렛은 밀라노 시내에서 약 70km 거리입니다.\n\n• 셔틀버스: 두오모 인근 출발, 편도 약 1시간, 왕복 €20\n• 기차+버스: 중앙역 → 아르콰타 스크리비아(약 1시간) → 셔틀(15분)\n\n셔틀버스가 가장 편리합니다. 예약 링크를 정리해 드릴까요?' - } - ], - '계약서 핵심 조항 요약해줘': [ - { role: 'user', text: '첨부한 계약서에서 핵심 조항만 요약해줘.' }, - { - role: 'bot', - text: - '핵심 조항 요약입니다.\n\n1. 계약 기간: 2026-07-01 ~ 2027-06-30 (1년, 자동 갱신)\n2. 대금 지급: 매월 말일, 세금계산서 발행 후 30일 이내\n3. 위약금: 중도 해지 시 잔여 계약금액의 20%\n4. 비밀유지: 계약 종료 후 3년간\n\n특정 조항을 더 자세히 볼까요?' - }, - { role: 'user', text: '위약금 조항만 더 자세히.' }, - { - role: 'bot', - text: - '제8조(위약금) 상세입니다.\n\n• 산정: 잔여 계약 기간 × 월 계약금액 × 20%\n• 예외: 천재지변·법령 변경 등 불가항력 시 면제\n• 감면: 해지 30일 전 서면 통지 시 50% 감면\n\n원문(제8조, 4페이지)을 인용으로 표시해 드릴까요?' - } - ], - '고객 불만 이메일 정중하게 회신': [ - { role: 'user', text: '배송 지연으로 화가 난 고객에게 보낼 정중한 사과 회신 작성해줘.' }, - { - role: 'bot', - text: - '아래 초안을 제안합니다.\n\n제목: 배송 지연에 대해 진심으로 사과드립니다\n\n안녕하세요 고객님,\n\n주문하신 상품의 배송이 지연되어 불편을 끼쳐 드린 점 진심으로 사과드립니다. 확인 결과 예상 도착일은 6월 30일입니다.\n\n사과의 뜻으로 다음 구매 시 사용 가능한 10% 할인 쿠폰을 보내드렸습니다.\n\n감사합니다.\n\n톤을 더 격식 있게 또는 캐주얼하게 조정할까요?' - } - ], - '월간 매출 데이터 피벗 분석': [ - { role: 'user', text: '첨부한 6월 매출 데이터로 카테고리별 피벗 분석해줘.' }, - { - role: 'bot', - text: - '6월 매출 피벗 분석 결과입니다.\n\n• 총 매출: ₩4.82억 (전월 대비 +8.3%)\n• 1위 카테고리: 신선식품 ₩1.61억 (33%)\n• 성장률 1위: 가공식품 +21%\n• 하락: 음료 -4%\n\n주말 매출이 평일 대비 1.7배입니다. 카테고리×주차 교차표도 만들어 드릴까요?' - }, - { role: 'user', text: '응, 주차별 교차표 만들어줘.' }, - { - role: 'bot', - text: - '주차 × 카테고리 교차표를 시트2에 생성했습니다.\n\n가장 큰 변동은 4주차 신선식품(+38%)으로, 가정의 달 프로모션 영향으로 보입니다. 해당 셀에 메모를 추가했습니다.' - } - ] -} - -function buildThread(c: Conversation): Turn[] { - const t = THREADS[c.title] - if (t) return t - return [ - { role: 'user', text: c.title }, - { - role: 'bot', - text: `${c.app}에서 요청하신 내용을 처리했습니다. 결과 초안을 정리해 드렸으니 확인 후 수정할 부분을 알려주세요.` - }, - { role: 'user', text: '좋아, 조금만 더 다듬어줘.' }, - { role: 'bot', text: '핵심 내용을 더 간결하게 정리하고 항목별로 구분했습니다. 추가로 반영할 부분이 있으면 말씀해 주세요.' } - ] -} - export function Conversations({ source }: PageProps): JSX.Element { const { t } = useTranslation('conversations') function scopeLabel(s: Scope): string { @@ -175,6 +108,7 @@ export function Conversations({ source }: PageProps): JSX.Element { const [selectedUserKey, setSelectedUserKey] = useState(ALL_USER_KEY) const [selected, setSelected] = useState(null) const [thread, setThread] = useState([]) + const [threadError, setThreadError] = useState(null) const agentDisplayName = (conversation: Conversation): string => { const name = conversation.agent?.trim() @@ -188,14 +122,17 @@ export function Conversations({ source }: PageProps): JSX.Element { if (name && !isTechnicalAgentName(name)) return name return name ? t('agents.unnamed', { id: compactAgentId(name) }) : t('agents.unknown') } - const basePayload = { - source, - search: applied.search.trim() || undefined, - scope: applied.scope, - app: applied.app || undefined, - dateFrom: applied.dateFrom || undefined, - dateTo: applied.dateTo || undefined - } + const basePayload = useMemo( + () => ({ + source, + search: applied.search.trim() || undefined, + scope: applied.scope, + app: applied.app || undefined, + dateFrom: applied.dateFrom || undefined, + dateTo: applied.dateTo || undefined + }), + [source, applied] + ) const agentTotal = agentFacets.reduce((sum, facet) => sum + facet.count, 0) const userTotal = userFacets.reduce((sum, facet) => sum + facet.count, 0) const selectedAgent = agentFacets.find((facet) => facet.key === selectedAgentKey) @@ -286,7 +223,7 @@ export function Conversations({ source }: PageProps): JSX.Element { active = false if (timer) clearInterval(timer) } - }, [source, applied]) + }, [source, basePayload]) useEffect(() => { if (selectedAgentKey === ALL_AGENT_KEY) return @@ -329,7 +266,7 @@ export function Conversations({ source }: PageProps): JSX.Element { active = false if (timer) clearInterval(timer) } - }, [source, applied, selectedAgentKey]) + }, [source, basePayload, selectedAgentKey]) // Fetch one bounded page for the selected agent/user scope. useEffect(() => { @@ -367,7 +304,7 @@ export function Conversations({ source }: PageProps): JSX.Element { active = false if (timer) clearInterval(timer) } - }, [source, applied, selectedAgentKey, selectedUserKey, page]) + }, [source, basePayload, selectedAgentKey, selectedUserKey, page]) useEffect(() => { setSelected((current) => { @@ -381,18 +318,33 @@ export function Conversations({ source }: PageProps): JSX.Element { }, [page, pageCount]) useEffect(() => { + setThreadError(null) if (!selected) { setThread([]) return } + // A conversation without a stable id cannot be resolved back to stored + // interactions. Never synthesise turns here — this view is evidence. if (!selected.id) { - setThread(buildThread(selected)) + setThread([]) + setThreadError(t('threadUnavailable')) return } + let active = true invoke('conversation_thread', selected.id) - .then((t) => setThread(t ?? [])) - .catch(() => setThread([])) - }, [selected]) + .then((rows) => { + if (!active) return + setThread(Array.isArray(rows) ? rows : []) + }) + .catch((e: unknown) => { + if (!active) return + setThread([]) + setThreadError(t('threadLoadFailed', { message: e instanceof Error ? e.message : String(e) })) + }) + return () => { + active = false + } + }, [selected, t]) const apply = (e: React.FormEvent): void => { e.preventDefault() @@ -703,7 +655,9 @@ export function Conversations({ source }: PageProps): JSX.Element {

- {thread.length === 0 ? ( + {threadError ? ( +
{threadError}
+ ) : thread.length === 0 ? (
{t('noMessages')}
) : ( thread.map((t2, i) => ( diff --git a/src/renderer/src/pages/Security.tsx b/src/renderer/src/pages/Security.tsx index cf3146f..4a2b404 100644 --- a/src/renderer/src/pages/Security.tsx +++ b/src/renderer/src/pages/Security.tsx @@ -20,7 +20,14 @@ interface EventRow { raw: string } interface SecurityData { - kpis: { total: number; blocked: number; uniqueUsers: number; topOperation: string | null; topOperationCount: number } + kpis: { + total: number + blocked: number + uniqueUsers: number + topOperation: string | null + topOperationCount: number + truncated: boolean + } events: EventRow[] } interface DiagRow { @@ -42,7 +49,7 @@ interface Filters { } const EMPTY_DATA: SecurityData = { - kpis: { total: 0, blocked: 0, uniqueUsers: 0, topOperation: null, topOperationCount: 0 }, + kpis: { total: 0, blocked: 0, uniqueUsers: 0, topOperation: null, topOperationCount: 0, truncated: false }, events: [] } const EMPTY_FILTERS: Filters = { source: '', dateFrom: '', dateTo: '', search: '' } @@ -178,7 +185,10 @@ export function Security(): JSX.Element { - {t('count', { count: n(data.events.length) })} + + {t('count', { count: n(data.events.length) })} + {k.truncated ? ` · ${t('truncated', { shown: n(data.events.length), total: n(k.total) })}` : ''} +
diff --git a/src/renderer/src/styles.css b/src/renderer/src/styles.css index ec13a8f..72b4443 100644 --- a/src/renderer/src/styles.css +++ b/src/renderer/src/styles.css @@ -4,7 +4,7 @@ background, one violet accent, generous spacing, soft borders. ========================================================================== */ -@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable.css'); +@import 'pretendard/dist/web/variable/pretendardvariable.css'; :root { --bg: #0a0b0d; diff --git a/tests/csv.test.ts b/tests/csv.test.ts new file mode 100644 index 0000000..ddda330 --- /dev/null +++ b/tests/csv.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, it } from 'vitest' +import { toCsv } from '../src/main/csv' + +describe('toCsv', () => { + it('returns an empty string for no rows', () => { + expect(toCsv([])).toBe('') + }) + + it('writes a header row and CRLF line endings', () => { + expect(toCsv([{ id: 'a', n: 1 }, { id: 'b', n: 2 }])).toBe('id,n\r\na,1\r\nb,2') + }) + + it('quotes and escapes values that would otherwise break the row structure', () => { + const csv = toCsv([{ text: 'has "quotes", a comma\nand a newline' }]) + + expect(csv).toBe('text\r\n"has ""quotes"", a comma\nand a newline"') + }) + + it('renders null and undefined as empty cells rather than the literal words', () => { + expect(toCsv([{ a: null, b: undefined, c: 0, d: false }])).toBe('a,b,c,d\r\n,,0,false') + }) + + it('keeps the column set stable across rows with differing keys', () => { + // The first row defines the schema; a later row's extra key must not shift + // the columns of an already-written export. + expect(toCsv([{ a: 1 }, { a: 2, b: 3 } as Record])).toBe('a\r\n1\r\n2') + }) +}) diff --git a/tests/http-client.test.ts b/tests/http-client.test.ts new file mode 100644 index 0000000..21dd82c --- /dev/null +++ b/tests/http-client.test.ts @@ -0,0 +1,151 @@ +import { describe, expect, it, vi } from 'vitest' +import { httpJson, httpRequest, retryDelayMs, HttpError, HttpTimeoutError, MAX_THROTTLE_RETRIES } from '../src/main/http' + +function response(status: number, body = '', headers: Record = {}): Response { + return new Response(body, { status, headers }) +} + +/** A `fetch` stand-in that replays a scripted sequence and records its calls. */ +function scriptedFetch(sequence: Array): { + impl: typeof fetch + calls: () => number +} { + let index = 0 + const impl = (async () => { + const next = sequence[Math.min(index, sequence.length - 1)] + index++ + if (next instanceof Error) throw next + return next.clone() + }) as unknown as typeof fetch + return { impl, calls: () => index } +} + +describe('retryDelayMs', () => { + it('honours a numeric Retry-After', () => { + expect(retryDelayMs(response(429, '', { 'retry-after': '7' }), 0)).toBe(7000) + }) + + it('honours an HTTP-date Retry-After', () => { + const at = new Date(Date.now() + 30_000).toUTCString() + const delay = retryDelayMs(response(429, '', { 'retry-after': at }), 0) + expect(delay).toBeGreaterThan(20_000) + expect(delay).toBeLessThanOrEqual(60_000) + }) + + it('backs off exponentially without a header and caps at 60s', () => { + expect(retryDelayMs(response(503), 0)).toBe(1000) + expect(retryDelayMs(response(503), 3)).toBe(8000) + expect(retryDelayMs(response(503), 20)).toBe(60_000) + }) +}) + +describe('httpRequest', () => { + it('retries a throttled GET and returns the eventual success', async () => { + const { impl, calls } = scriptedFetch([ + response(429, '', { 'retry-after': '0' }), + response(429, '', { 'retry-after': '0' }), + response(200, 'ok') + ]) + const res = await httpRequest('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl, maxRetries: 3 }) + + expect(res.status).toBe(200) + expect(calls()).toBe(3) + }) + + it('does not retry a POST on 5xx, where the outcome is unknown', async () => { + const { impl, calls } = scriptedFetch([response(503), response(200)]) + const res = await httpRequest('https://graph.microsoft.com/v1.0/x', { method: 'POST' }, { fetchImpl: impl }) + + expect(res.status).toBe(503) + expect(calls()).toBe(1) + }) + + it('retries a POST on 429, where the server states it did not process the request', async () => { + const { impl, calls } = scriptedFetch([response(429, '', { 'retry-after': '0' }), response(201)]) + const res = await httpRequest('https://graph.microsoft.com/v1.0/x', { method: 'POST' }, { fetchImpl: impl }) + + expect(res.status).toBe(201) + expect(calls()).toBe(2) + }) + + it('gives up after maxRetries instead of looping forever', async () => { + const { impl, calls } = scriptedFetch([response(503)]) + // Backoff is exponential (1s, 2s, …), so keep the budget small to stay fast. + const res = await httpRequest('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl, maxRetries: 2 }) + + expect(res.status).toBe(503) + expect(calls()).toBe(3) + }) + + it('defaults to a bounded number of throttle retries', () => { + expect(MAX_THROTTLE_RETRIES).toBeGreaterThan(0) + expect(MAX_THROTTLE_RETRIES).toBeLessThanOrEqual(10) + }) + + it('refreshes the token exactly once on 401', async () => { + const { impl, calls } = scriptedFetch([response(401), response(200)]) + const onUnauthorized = vi.fn().mockResolvedValue(true) + const res = await httpRequest('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl, onUnauthorized }) + + expect(res.status).toBe(200) + expect(onUnauthorized).toHaveBeenCalledTimes(1) + expect(calls()).toBe(2) + }) + + it('does not refresh again when the refreshed token is still rejected', async () => { + const { impl, calls } = scriptedFetch([response(401)]) + const onUnauthorized = vi.fn().mockResolvedValue(true) + const res = await httpRequest('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl, onUnauthorized }) + + expect(res.status).toBe(401) + expect(onUnauthorized).toHaveBeenCalledTimes(1) + expect(calls()).toBe(2) + }) + + it('aborts a hung request rather than hanging the main process forever', async () => { + const impl = ((_url: string, init?: RequestInit) => + new Promise((_resolve, reject) => { + init?.signal?.addEventListener('abort', () => reject(new DOMException('aborted', 'AbortError'))) + })) as unknown as typeof fetch + + await expect(httpRequest('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl, timeoutMs: 20 })).rejects.toBeInstanceOf( + HttpTimeoutError + ) + }) + + it('propagates caller cancellation', async () => { + const controller = new AbortController() + const impl = ((_url: string, init?: RequestInit) => + new Promise((_resolve, reject) => { + init?.signal?.addEventListener('abort', () => reject(new DOMException('aborted', 'AbortError'))) + })) as unknown as typeof fetch + + const pending = httpRequest('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl, signal: controller.signal }) + controller.abort() + + // Caller cancellation is not a timeout, so the original abort surfaces. + await expect(pending).rejects.not.toBeInstanceOf(HttpTimeoutError) + }) +}) + +describe('httpJson', () => { + it('throws instead of silently degrading a non-JSON body to an empty object', async () => { + const { impl } = scriptedFetch([response(200, 'Sign in')]) + + await expect(httpJson('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl })).rejects.toBeInstanceOf(HttpError) + }) + + it('throws on a non-2xx response', async () => { + const { impl } = scriptedFetch([response(403, 'Forbidden')]) + + await expect(httpJson('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl })).rejects.toBeInstanceOf(HttpError) + }) + + it('parses a JSON body', async () => { + const { impl } = scriptedFetch([response(200, JSON.stringify({ value: [1, 2] }))]) + + await expect(httpJson<{ value: number[] }>('https://graph.microsoft.com/v1.0/me', {}, { fetchImpl: impl })).resolves.toEqual({ + value: [1, 2] + }) + }) +}) diff --git a/tests/thread-upsert.test.ts b/tests/thread-upsert.test.ts new file mode 100644 index 0000000..ed85516 --- /dev/null +++ b/tests/thread-upsert.test.ts @@ -0,0 +1,112 @@ +import { mkdtempSync, readFileSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join, resolve } from 'node:path' +import { DatabaseSync } from 'node:sqlite' +import { afterAll, beforeAll, describe, expect, it } from 'vitest' +import * as db from '../src/main/db' +import type { ThreadGroup } from '../src/main/threading' + +let tempDir = '' +let dbPath = '' + +const THREAD_ID = 'thread-attribution-1' + +function thread(overrides: Partial = {}): ThreadGroup { + return { + id: THREAD_ID, + userId: 'user-000', + startedAt: '2026-01-01T00:00:00.000Z', + endedAt: '2026-01-01T00:05:00.000Z', + app: 'BizChat', + turnCount: 2, + promptCount: 1, + responseCount: 1, + sessionIds: [], + interactionIds: [], + title: 'Original title', + ...overrides + } +} + +function readThread(): Record { + const raw = new DatabaseSync(dbPath, { readOnly: true }) + try { + return raw.prepare('SELECT * FROM conversation_threads WHERE id = ?').get(THREAD_ID) as Record + } finally { + raw.close() + } +} + +beforeAll(() => { + tempDir = mkdtempSync(join(tmpdir(), 'cwt-thread-upsert-')) + dbPath = join(tempDir, 'store.db') + const raw = new DatabaseSync(dbPath) + raw.exec(readFileSync(resolve('resources/schema.sql'), 'utf8')) + raw.prepare('INSERT INTO settings(key,value) VALUES(?,?)').run('thread_agent_attribution_v1', '1') + raw + .prepare('INSERT INTO users(id,upn,display_name,enabled,has_copilot_license,in_scope) VALUES(?,?,?,?,?,?)') + .run('user-000', 'user-000@example.com', 'User 000', 1, 1, 1) + raw.close() + + process.env.CWT_DB_PATH = dbPath + expect(db.openDb()).toBe(true) +}) + +afterAll(() => { + db.closeDb() + delete process.env.CWT_DB_PATH + rmSync(tempDir, { recursive: true, force: true }) +}) + +describe('upsertThreads', () => { + it('preserves agent attribution across a re-collection', () => { + db.upsertThreads([thread()], 'api') + + // Attribution is written by a separate backfill pass, not by the collector. + const raw = new DatabaseSync(dbPath) + raw + .prepare('UPDATE conversation_threads SET agent_key=?, agent_id=?, agent_name=? WHERE id=?') + .run('api::agent-7', 'agent-7', 'HR Assistant', THREAD_ID) + raw.close() + + // Re-collect the same thread with refreshed counts, as a second run would. + db.upsertThreads([thread({ title: 'Updated title', turnCount: 4, promptCount: 2, responseCount: 2 })], 'api') + + const row = readThread() + expect(row.title).toBe('Updated title') + expect(row.turn_count).toBe(4) + // INSERT OR REPLACE is a DELETE+INSERT in SQLite, which used to blank these. + expect(row.agent_key).toBe('api::agent-7') + expect(row.agent_id).toBe('agent-7') + expect(row.agent_name).toBe('HR Assistant') + }) + + it('still updates every collector-owned column', () => { + db.upsertThreads( + [thread({ app: 'Teams', title: 'Third pass', endedAt: '2026-01-02T00:00:00.000Z' })], + 'ediscovery' + ) + + const row = readThread() + expect(row.app).toBe('Teams') + expect(row.title).toBe('Third pass') + expect(row.ended_at).toBe('2026-01-02T00:00:00.000Z') + expect(row.source_type).toBe('ediscovery') + expect(row.agent_name).toBe('HR Assistant') + }) +}) + +describe('query helpers', () => { + it('escapes LIKE wildcards in operator-supplied search text', () => { + // Without escaping, "%" and "_" silently match everything. + expect(db.likeNeedle('50%')).toBe('%50\\%%') + expect(db.likeNeedle('a_b')).toBe('%a\\_b%') + expect(db.likeNeedle('C:\\temp')).toBe('%c:\\\\temp%') + expect(db.likeNeedle(' Mixed Case ')).toBe('%mixed case%') + }) + + it('uses an inclusive end-of-day bound so the last second is not dropped', () => { + expect(db.endOfDay('2026-03-04')).toBe('2026-03-04T23:59:59.999Z') + expect('2026-03-04T23:59:59.500Z' <= db.endOfDay('2026-03-04')).toBe(true) + }) +}) diff --git a/tests/window-security.test.ts b/tests/window-security.test.ts index ee1b2ee..5dce488 100644 --- a/tests/window-security.test.ts +++ b/tests/window-security.test.ts @@ -1,14 +1,31 @@ import { describe, expect, it } from 'vitest' -import { isAllowedPrimaryNavigation, isSafeExternalUrl } from '../src/main/windowSecurity' +import { isAllowedPrimaryNavigation, isSafeExternalUrl, isWebScheme } from '../src/main/windowSecurity' describe('primary window security policy', () => { - it('opens only credential-free HTTPS URLs externally', () => { + it('opens only credential-free HTTPS URLs on allowlisted Microsoft hosts', () => { expect(isSafeExternalUrl('https://microsoft.com/devicelogin')).toBe(true) expect(isSafeExternalUrl('https://user:password@example.com/')).toBe(false) expect(isSafeExternalUrl('http://example.com/')).toBe(false) expect(isSafeExternalUrl('file:///C:/Windows/System32/calc.exe')).toBe(false) expect(isSafeExternalUrl('javascript:alert(1)')).toBe(false) expect(isSafeExternalUrl('not a url')).toBe(false) + expect(isSafeExternalUrl('https://login.microsoftonline.com/common/oauth2/v2.0/authorize')).toBe(true) + expect(isSafeExternalUrl('https://admin.powerplatform.microsoft.com/')).toBe(true) + }) + + it('refuses hosts outside the allowlist, including lookalikes', () => { + expect(isSafeExternalUrl('https://example.com/')).toBe(false) + expect(isSafeExternalUrl('https://microsoft.com.evil.test/')).toBe(false) + expect(isSafeExternalUrl('https://notmicrosoft.com/')).toBe(false) + }) + + it('allows only web schemes inside interactive portal windows', () => { + expect(isWebScheme('https://login.microsoftonline.com/')).toBe(true) + expect(isWebScheme('http://localhost:5173/')).toBe(true) + expect(isWebScheme('file:///C:/Windows/System32/config/SAM')).toBe(false) + expect(isWebScheme('javascript:alert(1)')).toBe(false) + expect(isWebScheme('ms-appinstaller:?source=https://evil.test/x.msix')).toBe(false) + expect(isWebScheme('nope')).toBe(false) }) it('keeps development navigation on the renderer origin', () => { diff --git a/tests/zip64.test.ts b/tests/zip64.test.ts new file mode 100644 index 0000000..d4ec44a --- /dev/null +++ b/tests/zip64.test.ts @@ -0,0 +1,165 @@ +import { describe, expect, it } from 'vitest' +import { deflateRawSync } from 'node:zlib' +import { readZipEntries } from '../src/main/collectors/ediscoveryExport' + +interface Entry { + name: string + data: Buffer + /** Force the ZIP64 encoding for this entry regardless of its size. */ + zip64?: boolean +} + +const U32_MAX = 0xffffffff + +/** + * Build a ZIP by hand so the reader can be exercised against both the classic + * and the ZIP64 encoding without checking multi-gigabyte fixtures into the repo. + */ +function buildZip(entries: Entry[], opts: { zip64Eocd?: boolean } = {}): Buffer { + const locals: Buffer[] = [] + const centrals: Buffer[] = [] + let offset = 0 + + for (const entry of entries) { + const name = Buffer.from(entry.name, 'utf8') + const comp = deflateRawSync(entry.data) + + const local = Buffer.alloc(30) + local.writeUInt32LE(0x04034b50, 0) + local.writeUInt16LE(20, 4) // version needed + local.writeUInt16LE(8, 8) // method: deflate + local.writeUInt32LE(comp.length, 18) + local.writeUInt32LE(entry.data.length, 22) + local.writeUInt16LE(name.length, 26) + local.writeUInt16LE(0, 28) + locals.push(local, name, comp) + + const central = Buffer.alloc(46) + central.writeUInt32LE(0x02014b50, 0) + central.writeUInt16LE(20, 6) + central.writeUInt16LE(8, 10) + + let extra = Buffer.alloc(0) + if (entry.zip64) { + // Saturate compressed size + local header offset, and describe both in a + // 0x0001 extra field, in the fixed order the spec mandates. + const field = Buffer.alloc(24) + field.writeBigUInt64LE(BigInt(entry.data.length), 0) + field.writeBigUInt64LE(BigInt(comp.length), 8) + field.writeBigUInt64LE(BigInt(offset), 16) + extra = Buffer.alloc(4 + field.length) + extra.writeUInt16LE(0x0001, 0) + extra.writeUInt16LE(field.length, 2) + field.copy(extra, 4) + + central.writeUInt32LE(U32_MAX, 20) + central.writeUInt32LE(U32_MAX, 24) + central.writeUInt32LE(U32_MAX, 42) + } else { + central.writeUInt32LE(comp.length, 20) + central.writeUInt32LE(entry.data.length, 24) + central.writeUInt32LE(offset, 42) + } + central.writeUInt16LE(name.length, 28) + central.writeUInt16LE(extra.length, 30) + centrals.push(central, name, extra) + + offset += local.length + name.length + comp.length + } + + const localBlock = Buffer.concat(locals) + const centralBlock = Buffer.concat(centrals) + const cdOffset = localBlock.length + const parts: Buffer[] = [localBlock, centralBlock] + + let eocdCount = entries.length + let eocdOffset = cdOffset + if (opts.zip64Eocd) { + eocdCount = 0xffff + eocdOffset = U32_MAX + + const eocd64 = Buffer.alloc(56) + eocd64.writeUInt32LE(0x06064b50, 0) + eocd64.writeBigUInt64LE(BigInt(44), 4) // size of remaining record + eocd64.writeBigUInt64LE(BigInt(entries.length), 24) // entries on this disk + eocd64.writeBigUInt64LE(BigInt(entries.length), 32) // total entries + eocd64.writeBigUInt64LE(BigInt(centralBlock.length), 40) + eocd64.writeBigUInt64LE(BigInt(cdOffset), 48) + + const locator = Buffer.alloc(20) + locator.writeUInt32LE(0x07064b50, 0) + locator.writeBigUInt64LE(BigInt(localBlock.length + centralBlock.length), 8) + locator.writeUInt32LE(1, 16) + + parts.push(eocd64, locator) + } + + const eocd = Buffer.alloc(22) + eocd.writeUInt32LE(0x06054b50, 0) + eocd.writeUInt16LE(eocdCount, 8) + eocd.writeUInt16LE(eocdCount, 10) + eocd.writeUInt32LE(centralBlock.length, 12) + eocd.writeUInt32LE(eocdOffset, 16) + parts.push(eocd) + + return Buffer.concat(parts) +} + +describe('readZipEntries', () => { + it('reads a classic (non-ZIP64) package', () => { + const zip = buildZip([ + { name: 'a.txt', data: Buffer.from('hello') }, + { name: 'b.json', data: Buffer.from('{"x":1}') } + ]) + + expect(readZipEntries(zip).map((e) => [e.name, e.data.toString()])).toEqual([ + ['a.txt', 'hello'], + ['b.json', '{"x":1}'] + ]) + }) + + it('reads a ZIP64 package whose EOCD fields are saturated', () => { + const zip = buildZip( + [ + { name: 'big/one.txt', data: Buffer.from('first'), zip64: true }, + { name: 'big/two.txt', data: Buffer.from('second'), zip64: true } + ], + { zip64Eocd: true } + ) + + expect(readZipEntries(zip).map((e) => [e.name, e.data.toString()])).toEqual([ + ['big/one.txt', 'first'], + ['big/two.txt', 'second'] + ]) + }) + + it('reads ZIP64 per-entry offsets even with a classic EOCD', () => { + const zip = buildZip([{ name: 'mixed.txt', data: Buffer.from('payload'), zip64: true }]) + + expect(readZipEntries(zip)).toEqual([{ name: 'mixed.txt', data: Buffer.from('payload') }]) + }) + + it('reports rather than swallows a package with no central directory', () => { + const warnings: string[] = [] + + expect(readZipEntries(Buffer.from('not a zip at all'), (line) => warnings.push(line))).toEqual([]) + expect(warnings).toHaveLength(1) + expect(warnings[0]).toMatch(/EOCD/) + }) + + it('reports a corrupt entry instead of yielding an empty buffer for it', () => { + const zip = buildZip([ + { name: 'good.txt', data: Buffer.from('fine') }, + { name: 'bad.txt', data: Buffer.from('doomed') } + ]) + // Corrupt the second entry's deflate stream in place. + const at = zip.indexOf(Buffer.from('bad.txt')) + 'bad.txt'.length + zip.fill(0xff, at, at + 6) + + const warnings: string[] = [] + const entries = readZipEntries(zip, (line) => warnings.push(line)) + + expect(entries.map((e) => e.name)).toEqual(['good.txt']) + expect(warnings.join(' ')).toMatch(/bad\.txt/) + }) +})