diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1b533a4..ac82e1a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -13,12 +13,12 @@ jobs: steps: - name: Install Nodejs - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 22 - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -39,3 +39,56 @@ jobs: - name: Package extension run: npx vsce package + + prerelease-code-marketplace: + name: 'Pre-release (Code Marketplace)' + runs-on: ubuntu-latest + needs: test + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + steps: + - name: Install Nodejs + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: 22 + + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - run: npm ci + + - name: Set pre-release version + run: | + MAJOR_MINOR=$(node -p "require('./package.json').version.split('.').slice(0,2).join('.')") + npm version "${MAJOR_MINOR}.$(date -u +'%Y%m%d%H%M')" --no-git-tag-version + + - name: Publish Extension (Code Marketplace, pre-release) + run: npx vsce publish --pre-release --pat ${{ secrets.MARKETPLACE_TOKEN }} + + prerelease-openvsx: + name: 'Pre-release (OpenVSX)' + runs-on: ubuntu-latest + needs: test + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + steps: + - name: Install Nodejs + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version: 22 + + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - run: npm ci + + - name: Set pre-release version + run: | + MAJOR_MINOR=$(node -p "require('./package.json').version.split('.').slice(0,2).join('.')") + npm version "${MAJOR_MINOR}.$(date -u +'%Y%m%d%H%M')" --no-git-tag-version + + - name: Publish Extension (OpenVSX, pre-release) + run: npx ovsx publish --pre-release --pat ${{ secrets.OPENVSX_TOKEN }} + timeout-minutes: 2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 357f4dc..b00607f 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -11,12 +11,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Install Nodejs - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 22 - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: ${{ env.FETCH_DEPTH }} @@ -35,12 +35,12 @@ jobs: needs: check-version steps: - name: Install Nodejs - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 22 - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -57,12 +57,12 @@ jobs: needs: check-version steps: - name: Install Nodejs - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: 22 - name: Checkout repository - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 diff --git a/.vscode-test.mjs b/.vscode-test.mjs deleted file mode 100644 index db34f3e..0000000 --- a/.vscode-test.mjs +++ /dev/null @@ -1,5 +0,0 @@ -import { defineConfig } from '@vscode/test-cli'; - -export default defineConfig({ - files: 'out/test/**/*.test.js', -}); diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b72ebe..d820377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,37 +5,49 @@ All notable changes to the "pixi-code" extension will be documented in this file The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.1.5] - 2025-09-13 +## [Pre-release] + +- Support `python-envs.workspaceSearchPaths` and `python-envs.globalSearchPaths` for environment discovery +- Fix `pixi-code.pixiExecutable` setting not being read +- Fix subprocess runner race condition between exit and close events +- Fix fire-and-forget promises in environment selection +- Remove broken `deactivate` function (VS Code handles cleanup automatically) +- Extract shared helpers and parallelize environment discovery +- Add pre-release pipeline for continuous updates on every push to main +- Revert 0.1.5 `activatedRun` change now that https://github.com/microsoft/vscode-python-debugger/pull/949 was merged +- Remove `defaultInterpreterPath` support for setting the active environment + +## [0.1.5] - Fix debugging Pixi projects in the new version of the Python Environments extension by fixing the `activatedRun` command. -## [0.1.4] - 2025-09-13 +## [0.1.4] - Check if project path exists before running Pixi commands - Check minimum Pixi version on activation - Remove unsupported actions (create, quick create and remove) for better UX -## [0.1.3] - 2025-08-24 +## [0.1.3] ### Added - If `defaultInterpreterPath` is set and no Pixi environment was manually selected, use it as the project's interpreter - Publish to OpenVSX -## [0.1.2] - 2025-07-27 +## [0.1.2] ### Fixed - Deduplicate envs returned by getEnvironments -## [0.1.1] - 2025-07-27 +## [0.1.1] ### Fixed - Fix error messages only showing in debug mode -## [0.1.0] - 2025-07-27 +## [0.1.0] ### Added diff --git a/README.md b/README.md index 2a1eb25..f5ba625 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ conda, venv, and other Python environments in VS Code. - Automatic discovery of Python environments created with Pixi - Automatic interpreter selection when running and debugging Python code -- Respect `defaultInterpreterPath` if no Pixi environment was manually selected - Support for Pixi features (dev, test, lint, etc.) as separate selectable environments - Terminal activation - Persistent environment selection per project @@ -44,7 +43,7 @@ The extension will automatically discover Pixi environments and register them wi ## Extension Settings -- `pixi-code.pixiExecutable`: Path to the Pixi executable (default: pixi). If empty, autodiscovery will be used. +- `pixi-code.pixiExecutable`: Path to the Pixi executable. Leave empty to use auto-discovery (default). ## Limitations diff --git a/RELEASE.md b/RELEASE.md index bbd4810..1b7199f 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,6 +1,12 @@ # Release Process -## Steps to Release +## Pre-release + +Every push to `main` automatically publishes a pre-release version to both the VS Code +Marketplace and OpenVSX. Users who opt-in to pre-release versions in their editor will +receive these updates automatically. + +## Stable Release 1. **Create a PR updating package.json version and package-lock.json** diff --git a/package-lock.json b/package-lock.json index 948580a..fbf8279 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,35 +1,38 @@ { "name": "pixi-code", - "version": "0.1.5", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pixi-code", - "version": "0.1.5", + "version": "0.2.0", "license": "MIT", "dependencies": { "@types/semver": "^7.7.1", - "semver": "^7.7.2", - "which": "^5.0.0" + "fast-glob": "^3.3.3", + "fs-extra": "^11.3.4", + "semver": "^7.7.4", + "which": "^6.0.1" }, "devDependencies": { + "@types/fs-extra": "^11.0.4", "@types/node": "24.x", - "@types/vscode": "^1.103.0", + "@types/vscode": "^1.109.0", "@types/which": "^3.0.4", - "@typescript-eslint/eslint-plugin": "^8.40.0", - "@typescript-eslint/parser": "^8.40.0", - "eslint": "^9.34.0", + "@typescript-eslint/eslint-plugin": "^8.56.1", + "@typescript-eslint/parser": "^8.56.1", + "eslint": "^10.0.3", "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^4.2.0", - "prettier": "^3.6.2", + "eslint-plugin-unused-imports": "^4.4.1", + "prettier": "^3.8.1", "ts-loader": "^9.5.4", - "typescript": "^5.9.2", - "webpack": "^5.101.3", + "typescript": "^5.9.3", + "webpack": "^5.105.4", "webpack-cli": "^6.0.1" }, "engines": { - "vscode": "^1.103.0" + "vscode": "^1.110.0" } }, "node_modules/@discoveryjs/json-ext": { @@ -43,9 +46,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -62,9 +65,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { @@ -72,160 +75,68 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "version": "0.23.3", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.3.tgz", + "integrity": "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", + "@eslint/object-schema": "^3.0.3", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^10.2.4" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.3.tgz", + "integrity": "sha512-lzGN0onllOZCGroKJmRwY6QcEHxbjBw1gwB8SgRSqK8YbbtEXMvKynsXc3553ckIEBxsbMBU7oOZXKIPGZNeZw==", "dev": true, "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.1.1" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.1.1.tgz", + "integrity": "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ==", "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.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "9.34.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", - "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.3.tgz", + "integrity": "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.6.1.tgz", + "integrity": "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.2", + "@eslint/core": "^1.1.1", "levn": "^0.4.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@humanfs/core": { @@ -295,9 +206,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { @@ -316,9 +227,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.10.tgz", - "integrity": "sha512-0pPkgz9dY+bijgistcTTJ5mR+ocqRXLuhXHYdzoMmmoJ2C9S46RCm2GMUbatPEUK9Yjy26IrAy8D/M00lLkv+Q==", + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { @@ -327,16 +238,16 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -348,7 +259,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -362,7 +272,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -372,7 +281,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -404,6 +312,13 @@ "@types/estree": "*" } }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -411,6 +326,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -418,6 +344,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "24.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", @@ -435,9 +371,9 @@ "license": "MIT" }, "node_modules/@types/vscode": { - "version": "1.103.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.103.0.tgz", - "integrity": "sha512-o4hanZAQdNfsKecexq9L3eHICd0AAvdbLk6hA60UzGXbGH/q8b/9xv2RgR7vV3ZcHuyKVq7b37IGd/+gM4Tu+Q==", + "version": "1.109.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.109.0.tgz", + "integrity": "sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw==", "dev": true, "license": "MIT" }, @@ -449,21 +385,20 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", - "integrity": "sha512-w/EboPlBwnmOBtRbiOvzjD+wdiZdgFeo17lkltrtn7X37vagKKWJABvyfsJXTlHe6XBzugmYgd4A4nW+k8Mixw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", + "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/type-utils": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/type-utils": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -473,23 +408,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.40.0", - "eslint": "^8.57.0 || ^9.0.0", + "@typescript-eslint/parser": "^8.56.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.40.0.tgz", - "integrity": "sha512-jCNyAuXx8dr5KJMkecGmZ8KI61KBUhkCob+SD+C+I5+Y1FWI2Y3QmY4/cxMCC5WAsZqoEtEETVhUiUMIGCf6Bw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", + "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -499,20 +434,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.40.0.tgz", - "integrity": "sha512-/A89vz7Wf5DEXsGVvcGdYKbVM9F7DyFXj52lNYUDS1L9yJfqjW/fIp5PgMuEJL/KeqVTe2QSbXAGUZljDUpArw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", + "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.40.0", - "@typescript-eslint/types": "^8.40.0", - "debug": "^4.3.4" + "@typescript-eslint/tsconfig-utils": "^8.56.1", + "@typescript-eslint/types": "^8.56.1", + "debug": "^4.4.3" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -526,14 +461,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.40.0.tgz", - "integrity": "sha512-y9ObStCcdCiZKzwqsE8CcpyuVMwRouJbbSrNuThDpv16dFAj429IkM6LNb1dZ2m7hK5fHyzNcErZf7CEeKXR4w==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", + "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -544,9 +479,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.40.0.tgz", - "integrity": "sha512-jtMytmUaG9d/9kqSl/W3E3xaWESo4hFDxAIHGVW/WKKtQhesnRIJSAJO6XckluuJ6KDB5woD1EiqknriCtAmcw==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", + "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", "dev": true, "license": "MIT", "engines": { @@ -561,17 +496,17 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.40.0.tgz", - "integrity": "sha512-eE60cK4KzAc6ZrzlJnflXdrMqOBaugeukWICO2rB0KNvwdIMaEaYiywwHMzA1qFpTxrLhN9Lp4E/00EgWcD3Ow==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", + "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0", - "@typescript-eslint/utils": "8.40.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1", + "@typescript-eslint/utils": "8.56.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -581,14 +516,14 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.40.0.tgz", - "integrity": "sha512-ETdbFlgbAmXHyFPwqUIYrfc12ArvpBhEVgGAxVYSwli26dn8Ko+lIo4Su9vI9ykTZdJn+vJprs/0eZU0YMAEQg==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", + "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", "dev": true, "license": "MIT", "engines": { @@ -600,22 +535,21 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.40.0.tgz", - "integrity": "sha512-k1z9+GJReVVOkc1WfVKs1vBrR5MIKKbdAjDTPvIK3L8De6KbFfPFt6BKpdkdk7rZS2GtC/m6yI5MYX+UsuvVYQ==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", + "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.40.0", - "@typescript-eslint/tsconfig-utils": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/visitor-keys": "8.40.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" + "@typescript-eslint/project-service": "8.56.1", + "@typescript-eslint/tsconfig-utils": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/visitor-keys": "8.56.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -629,16 +563,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.40.0.tgz", - "integrity": "sha512-Cgzi2MXSZyAUOY+BFwGs17s7ad/7L+gKt6Y8rAVVWS+7o6wrjeFN4nVfTpbE25MNcxyJ+iYUXflbs2xR9h4UBg==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", + "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.40.0", - "@typescript-eslint/types": "8.40.0", - "@typescript-eslint/typescript-estree": "8.40.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.56.1", + "@typescript-eslint/types": "8.56.1", + "@typescript-eslint/typescript-estree": "8.56.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -648,19 +582,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.40.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.40.0.tgz", - "integrity": "sha512-8CZ47QwalyRjsypfwnbI3hKy5gJDPmrkLjkgMxhi0+DZZ2QNx2naS6/hWoVYUHU7LU2zleF68V9miaVZvhFfTA==", + "version": "8.56.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", + "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.40.0", - "eslint-visitor-keys": "^4.2.1" + "@typescript-eslint/types": "8.56.1", + "eslint-visitor-keys": "^5.0.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -671,13 +605,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -906,9 +840,9 @@ "license": "Apache-2.0" }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { @@ -942,9 +876,9 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { @@ -977,9 +911,9 @@ } }, "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { @@ -1016,35 +950,46 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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==", + "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==", "dev": true, - "license": "Python-2.0" + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } }, - "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/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } }, "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -1054,9 +999,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -1074,10 +1019,11 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -1093,20 +1039,10 @@ "dev": true, "license": "MIT" }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/caniuse-lite": { - "version": "1.0.30001727", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz", - "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==", + "version": "1.0.30001777", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", + "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", "dev": true, "funding": [ { @@ -1200,13 +1136,6 @@ "dev": true, "license": "MIT" }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1246,9 +1175,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -1271,21 +1200,21 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.187", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz", - "integrity": "sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==", + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", "dev": true, "license": "ISC" }, "node_modules/enhanced-resolve": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", - "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" @@ -1305,9 +1234,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, @@ -1335,34 +1264,30 @@ } }, "node_modules/eslint": { - "version": "9.34.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", - "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.0.3.tgz", + "integrity": "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.1", - "@eslint/core": "^0.15.2", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.34.0", - "@eslint/plugin-kit": "^0.3.5", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.3", + "@eslint/config-helpers": "^0.5.2", + "@eslint/core": "^1.1.1", + "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", + "ajv": "^6.14.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", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.1.1", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", @@ -1372,8 +1297,7 @@ "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.2", + "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, @@ -1381,7 +1305,7 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" @@ -1406,14 +1330,14 @@ } }, "node_modules/eslint-plugin-unused-imports": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.2.0.tgz", - "integrity": "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz", + "integrity": "sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==", "dev": true, "license": "MIT", "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", - "eslint": "^9.0.0 || ^8.0.0" + "eslint": "^10.0.0 || ^9.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { @@ -1422,17 +1346,19 @@ } }, "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1451,25 +1377,14 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -1485,54 +1400,41 @@ "node": ">= 4" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -1596,7 +1498,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1613,7 +1514,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -1637,9 +1537,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", "dev": true, "funding": [ { @@ -1664,10 +1564,9 @@ } }, "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -1690,7 +1589,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -1747,6 +1645,20 @@ "dev": true, "license": "ISC" }, + "node_modules/fs-extra": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", + "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -1777,33 +1689,12 @@ "dev": true, "license": "BSD-2-Clause" }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1837,23 +1728,6 @@ "node": ">= 4" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", @@ -1914,7 +1788,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1924,7 +1797,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -1937,7 +1809,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -1957,12 +1828,12 @@ } }, "node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "license": "ISC", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=16" + "node": ">=20" } }, "node_modules/isobject": { @@ -2006,19 +1877,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2047,6 +1905,18 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2082,13 +1952,17 @@ } }, "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", + "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/locate-path": { @@ -2107,13 +1981,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -2125,7 +1992,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -2135,7 +2001,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -2169,16 +2034,16 @@ } }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2206,9 +2071,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, @@ -2272,19 +2137,6 @@ "node": ">=6" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2323,7 +2175,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -2412,9 +2263,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", "bin": { @@ -2441,7 +2292,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -2458,16 +2308,6 @@ ], "license": "MIT" }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", @@ -2535,21 +2375,10 @@ "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -2560,7 +2389,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -2580,31 +2408,10 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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" - }, "node_modules/schema-utils": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.2.tgz", - "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", "dev": true, "license": "MIT", "dependencies": { @@ -2622,9 +2429,9 @@ } }, "node_modules/schema-utils/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { @@ -2659,9 +2466,9 @@ "license": "MIT" }, "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -2670,16 +2477,6 @@ "node": ">=10" } }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", @@ -2747,19 +2544,6 @@ "node": ">=0.10.0" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2787,24 +2571,28 @@ } }, "node_modules/tapable": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", - "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", + "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -2816,16 +2604,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "version": "5.3.17", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", + "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", "terser": "^5.31.1" }, "engines": { @@ -2850,11 +2637,58 @@ } } }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -2864,9 +2698,9 @@ } }, "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", "dev": true, "license": "MIT", "engines": { @@ -2911,9 +2745,9 @@ } }, "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2931,10 +2765,19 @@ "dev": true, "license": "MIT" }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -2973,9 +2816,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", - "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", "dev": true, "license": "MIT", "dependencies": { @@ -2987,9 +2830,9 @@ } }, "node_modules/webpack": { - "version": "5.101.3", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz", - "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", + "version": "5.105.4", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", + "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", "dev": true, "license": "MIT", "dependencies": { @@ -2999,25 +2842,25 @@ "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", + "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", - "browserslist": "^4.24.0", + "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.3", - "es-module-lexer": "^1.2.1", + "enhanced-resolve": "^5.20.0", + "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", + "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.2", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.3.3" + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" }, "bin": { "webpack": "bin/webpack.js" @@ -3104,9 +2947,9 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", + "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", "dev": true, "license": "MIT", "engines": { @@ -3138,18 +2981,18 @@ } }, "node_modules/which": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz", + "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==", "license": "ISC", "dependencies": { - "isexe": "^3.1.1" + "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" }, "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/wildcard": { diff --git a/package.json b/package.json index 263fc57..ce61545 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Pixi support for the Python Environments extension", "icon": "assets/icon.png", "license": "MIT", - "version": "0.1.5", + "version": "0.2.0", "homepage": "https://github.com/renan-r-santos/pixi-code", "repository": { "type": "git", @@ -20,7 +20,7 @@ "conda" ], "engines": { - "vscode": "^1.103.0" + "vscode": "^1.110.0" }, "categories": [ "Data Science", @@ -37,12 +37,18 @@ ], "main": "./dist/extension.js", "contributes": { + "configurationDefaults": { + "python-envs.workspaceSearchPaths": [ + "./**/.venv", + "./**/.pixi" + ] + }, "configuration": { "title": "Pixi", "properties": { "pixi-code.pixiExecutable": { "type": "string", - "default": "pixi", + "default": "", "description": "Path to the Pixi executable. Leave empty to use auto-discovery.", "scope": "machine-overridable" } @@ -71,23 +77,26 @@ "format:check": "prettier --check ." }, "devDependencies": { + "@types/fs-extra": "^11.0.4", "@types/node": "24.x", - "@types/vscode": "^1.103.0", + "@types/vscode": "^1.109.0", "@types/which": "^3.0.4", - "@typescript-eslint/eslint-plugin": "^8.40.0", - "@typescript-eslint/parser": "^8.40.0", - "eslint": "^9.34.0", + "@typescript-eslint/eslint-plugin": "^8.56.1", + "@typescript-eslint/parser": "^8.56.1", + "eslint": "^10.0.3", "eslint-plugin-simple-import-sort": "^12.1.1", - "eslint-plugin-unused-imports": "^4.2.0", - "prettier": "^3.6.2", + "eslint-plugin-unused-imports": "^4.4.1", + "prettier": "^3.8.1", "ts-loader": "^9.5.4", - "typescript": "^5.9.2", - "webpack": "^5.101.3", + "typescript": "^5.9.3", + "webpack": "^5.105.4", "webpack-cli": "^6.0.1" }, "dependencies": { "@types/semver": "^7.7.1", - "semver": "^7.7.2", - "which": "^5.0.0" + "fast-glob": "^3.3.3", + "fs-extra": "^11.3.4", + "semver": "^7.7.4", + "which": "^6.0.1" } } diff --git a/src/api.ts b/src/api.ts index f2258cc..75014a7 100644 --- a/src/api.ts +++ b/src/api.ts @@ -4,6 +4,7 @@ import { Disposable, Event, + extensions, FileChangeType, LogOutputChannel, MarkdownString, @@ -14,6 +15,11 @@ import { Uri, } from 'vscode'; +/* + * Do not introduce any breaking changes to this API. + * This is the public API for other extensions to interact with the Python Environments extension. + */ + /** * The path to an icon, or a theme-specific configuration of icons. */ @@ -217,6 +223,13 @@ export interface PythonEnvironmentInfo { * Optional `group` for this environment. This is used to group environments in the Environment Manager UI. */ readonly group?: string | EnvironmentGroupInfo; + + /** + * Error message if the environment is broken or invalid. + * When set, indicates this environment has issues (e.g., broken symlinks, missing Python executable). + * The UI should display a warning indicator and show this message to help users diagnose and fix the issue. + */ + readonly error?: string; } /** @@ -379,7 +392,7 @@ export interface EnvironmentManager { quickCreateConfig?(): QuickCreateConfig | undefined; /** - * Creates a new Python environment within the specified scope. Create should support adding a .gitignore file if it creates a folder within the workspace. + * Creates a new Python environment within the specified scope. Create should support adding a .gitignore file if it creates a folder within the workspace. If a manager does not support environment creation, do not implement this method; the UI disables "create" options when `this.manager.create === undefined`. * @param scope - The scope within which to create the environment. * @param options - Optional parameters for creating the Python environment. * @returns A promise that resolves to the created Python environment, or undefined if creation failed. @@ -922,7 +935,8 @@ export interface PythonProjectEnvironmentApi { } export interface PythonEnvironmentManagerApi - extends PythonEnvironmentManagerRegistrationApi, + extends + PythonEnvironmentManagerRegistrationApi, PythonEnvironmentItemApi, PythonEnvironmentManagementApi, PythonEnvironmentsApi, @@ -987,7 +1001,8 @@ export interface PythonPackageManagementApi { } export interface PythonPackageManagerApi - extends PythonPackageManagerRegistrationApi, + extends + PythonPackageManagerRegistrationApi, PythonPackageGetterApi, PythonPackageManagementApi, PythonPackageItemApi {} @@ -1206,10 +1221,7 @@ export interface PythonBackgroundRunApi { } export interface PythonExecutionApi - extends PythonTerminalCreateApi, - PythonTerminalRunApi, - PythonTaskRunApi, - PythonBackgroundRunApi {} + extends PythonTerminalCreateApi, PythonTerminalRunApi, PythonTaskRunApi, PythonBackgroundRunApi {} /** * Event arguments for when the monitored `.env` files or any other sources change. @@ -1223,7 +1235,7 @@ export interface DidChangeEnvironmentVariablesEventArgs { /** * The type of change that occurred. */ - changeTye: FileChangeType; + changeType: FileChangeType; } export interface PythonEnvironmentVariablesApi { @@ -1237,12 +1249,13 @@ export interface PythonEnvironmentVariablesApi { * 3. `.env` file at the root of the python project. * 4. `overrides` in the order provided. * - * @param uri The URI of the project, workspace or a file in a for which environment variables are required. + * @param uri The URI of the project, workspace or a file in a for which environment variables are required.If not provided, + * it fetches the environment variables for the global scope. * @param overrides Additional environment variables to override the defaults. * @param baseEnvVar The base environment variables that should be used as a starting point. */ getEnvironmentVariables( - uri: Uri, + uri: Uri | undefined, overrides?: ({ [key: string]: string | undefined } | Uri)[], baseEnvVar?: { [key: string]: string | undefined }, ): Promise<{ [key: string]: string | undefined }>; @@ -1257,8 +1270,28 @@ export interface PythonEnvironmentVariablesApi { * The API for interacting with Python environments, package managers, and projects. */ export interface PythonEnvironmentApi - extends PythonEnvironmentManagerApi, + extends + PythonEnvironmentManagerApi, PythonPackageManagerApi, PythonProjectApi, PythonExecutionApi, PythonEnvironmentVariablesApi {} + +export const EXTENSION_ID = 'ms-python.vscode-python-envs'; + +export namespace PythonEnvironments { + /** + * Returns the API exposed by the Python Environments extension in VS Code. + */ + export async function api(): Promise { + const extension = extensions.getExtension(EXTENSION_ID); + if (extension === undefined) { + throw new Error(`Python Environments extension is not installed or is disabled`); + } + if (!extension.isActive) { + await extension.activate(); + } + const pythonEnvsApi: PythonEnvironmentApi = extension.exports; + return pythonEnvsApi; + } +} diff --git a/src/common/defaultInterpreter.ts b/src/common/defaultInterpreter.ts deleted file mode 100644 index ac7f644..0000000 --- a/src/common/defaultInterpreter.ts +++ /dev/null @@ -1,18 +0,0 @@ -import * as path from 'path'; -import { workspace } from 'vscode'; - -import { PythonProject } from '../api'; -import { expandVariables } from './variableExpansion'; - -export function getDefaultInterpreterPath(project: PythonProject): string | undefined { - const defaultInterpreterPath = workspace - .getConfiguration('python', project.uri) - .get('defaultInterpreterPath'); - - if (!defaultInterpreterPath) { - return undefined; - } - - const expandedPath = expandVariables(defaultInterpreterPath, project.uri); - return path.resolve(project.uri.fsPath, expandedPath); -} diff --git a/src/common/execUtils.ts b/src/common/execUtils.ts index 9cdfb67..6804d85 100644 --- a/src/common/execUtils.ts +++ b/src/common/execUtils.ts @@ -1,10 +1,21 @@ -function quoteArg(arg: string): string { - if (arg.indexOf(' ') >= 0 && !(arg.startsWith('"') && arg.endsWith('"'))) { - return `"${arg}"`; +export function quoteStringIfNecessary(arg: string): string { + // Always return if already quoted to avoid double-quoting + if (arg.startsWith('"') && arg.endsWith('"')) { + return arg; } - return arg; + + // Don't quote single shell operators/special characters + if (arg.length === 1 && /[&|<>;()[\]{}$]/.test(arg)) { + return arg; + } + + // Quote if contains common shell special characters that are problematic across multiple shells + // Includes: space, &, |, <, >, ;, ', ", `, (, ), [, ], {, }, $ + const needsQuoting = /[\s&|<>;'"`()\[\]{}$]/.test(arg); + + return needsQuoting ? `"${arg}"` : arg; } export function quoteArgs(args: string[]): string[] { - return args.map(quoteArg); + return args.map(quoteStringIfNecessary); } diff --git a/src/common/findPython.ts b/src/common/findPython.ts index 891580f..4cbe6e1 100644 --- a/src/common/findPython.ts +++ b/src/common/findPython.ts @@ -1,8 +1,7 @@ +import * as fs from 'fs-extra'; import * as os from 'os'; import * as path from 'path'; -import { fileExists } from './utils'; - export async function findPythonExecutable(envPath: string): Promise { let candidates; @@ -25,7 +24,7 @@ export async function findPythonExecutable(envPath: string): Promise; - constructor(private readonly momento: Memento) { + constructor(private readonly memento: Memento) { this.clearing = createDeferred(); this.clearing.resolve(); } async get(key: string, defaultValue?: T): Promise { await this.clearing.promise; if (defaultValue === undefined) { - return this.momento.get(key); + return this.memento.get(key); } - return this.momento.get(key, defaultValue); + return this.memento.get(key, defaultValue); } async set(key: string, value: T): Promise { await this.clearing.promise; - await this.momento.update(key, value); + await this.memento.update(key, value); const before = JSON.stringify(value); - const after = JSON.stringify(await this.momento.get(key)); + const after = JSON.stringify(await this.memento.get(key)); if (before !== after) { - await this.momento.update(key, undefined); + await this.memento.update(key, undefined); traceError('Error while updating state for key:', key); } } async clear(keys?: string[]): Promise { if (this.clearing.completed) { this.clearing = createDeferred(); - const _keys = keys ?? this.momento.keys(); - await Promise.all(_keys.map((key) => this.momento.update(key, undefined))); + const _keys = keys ?? this.memento.keys(); + await Promise.all(_keys.map((key) => this.memento.update(key, undefined))); this.clearing.resolve(); } return this.clearing.promise; @@ -45,23 +45,11 @@ class PersistentStateImpl implements PersistentState { } const _workspace = createDeferred(); -const _global = createDeferred(); export function setPersistentState(context: ExtensionContext): void { _workspace.resolve(new PersistentStateImpl(context.workspaceState)); - _global.resolve(new PersistentStateImpl(context.globalState)); } export function getWorkspacePersistentState(): Promise { return _workspace.promise; } - -export function getGlobalPersistentState(): Promise { - return _global.promise; -} - -export async function clearPersistentState(): Promise { - const [workspace, global] = await Promise.all([_workspace.promise, _global.promise]); - await Promise.all([workspace.clear(), global.clear()]); - return undefined; -} diff --git a/src/common/searchPaths.ts b/src/common/searchPaths.ts new file mode 100644 index 0000000..83b305f --- /dev/null +++ b/src/common/searchPaths.ts @@ -0,0 +1,118 @@ +import fg from 'fast-glob'; +import * as path from 'path'; +import { workspace } from 'vscode'; + +import { traceError, traceVerbose } from './logging'; +import { untildify } from './utils'; + +/** + * Reads `python-envs.workspaceSearchPaths` and `python-envs.globalSearchPaths`, + * resolves glob patterns, and returns deduplicated pixi project root paths. + */ +export async function resolvePixiProjectPaths(): Promise { + const workspacePaths = getWorkspaceSearchPaths(); + const globalPaths = getGlobalSearchPaths(); + + const resolvedWorkspace = resolveWorkspacePaths(workspacePaths); + const resolvedGlobal = globalPaths.map(untildify); + + const allPatterns = [...resolvedWorkspace, ...resolvedGlobal]; + + if (allPatterns.length === 0) { + return []; + } + + const pixiDirs = await findPixiDirectories(allPatterns); + const projectRoots = pixiDirs.map((dir) => path.dirname(dir)); + + return [...new Set(projectRoots.map(path.normalize))]; +} + +function getWorkspaceSearchPaths(): string[] { + try { + const config = workspace.getConfiguration('python-envs'); + const inspection = config.inspect('workspaceSearchPaths'); + + return inspection?.workspaceFolderValue ?? inspection?.workspaceValue ?? inspection?.defaultValue ?? []; + } catch (error) { + traceError('Error reading python-envs.workspaceSearchPaths:', error); + return []; + } +} + +function getGlobalSearchPaths(): string[] { + try { + const config = workspace.getConfiguration('python-envs'); + const inspection = config.inspect('globalSearchPaths'); + + return inspection?.globalValue ?? []; + } catch (error) { + traceError('Error reading python-envs.globalSearchPaths:', error); + return []; + } +} + +function resolveWorkspacePaths(searchPaths: string[]): string[] { + const folders = workspace.workspaceFolders; + const resolved: string[] = []; + + for (const rawPath of searchPaths) { + const expanded = untildify(rawPath.trim()); + if (!expanded) { + continue; + } + + if (path.isAbsolute(expanded)) { + resolved.push(expanded); + } else if (folders) { + for (const folder of folders) { + resolved.push(path.resolve(folder.uri.fsPath, expanded)); + } + } + } + + return resolved; +} + +async function findPixiDirectories(patterns: string[]): Promise { + const pixiPatterns: string[] = []; + + for (const pattern of patterns) { + const normalized = pattern.replace(/\\/g, '/').replace(/\/$/, ''); + const lastSegment = path.posix.basename(normalized); + + if (lastSegment === '.pixi') { + // Pattern explicitly targets .pixi directories + pixiPatterns.push(normalized); + } else if (lastSegment.startsWith('.')) { + // Targets another env type (e.g., .venv) — skip + continue; + } else { + // Generic directory — search for .pixi inside + pixiPatterns.push(`${normalized}/**/.pixi`); + } + } + + if (pixiPatterns.length === 0) { + return []; + } + + traceVerbose('Searching for .pixi directories with patterns:', pixiPatterns); + + try { + const results = await fg(pixiPatterns, { + onlyDirectories: true, + absolute: true, + dot: true, + followSymbolicLinks: false, + deep: 10, + suppressErrors: true, + }); + + traceVerbose(`Found ${results.length} .pixi directories`); + return results; + } catch (error) { + traceError('Error searching for .pixi directories:', error); + return []; + } +} diff --git a/src/common/utils.ts b/src/common/utils.ts index 5e9a8f3..0397f59 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -1,14 +1,8 @@ -import * as fs from 'fs'; import * as os from 'os'; export const EXTENSION_ID = 'renan-r-santos.pixi-code'; - -export const fileExists = async (path: string) => !!(await fs.promises.stat(path).catch((_) => false)); +export const PIXI_MANAGER_ID = `${EXTENSION_ID}:pixi`; export function untildify(path: string): string { return path.replace(/^~($|\/|\\)/, `${os.homedir()}$1`); } - -export function getUserHomeDir(): string { - return os.homedir(); -} diff --git a/src/common/variableExpansion.ts b/src/common/variableExpansion.ts deleted file mode 100644 index 8fdd3b4..0000000 --- a/src/common/variableExpansion.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Uri, workspace } from 'vscode'; - -export function expandVariables(value: string, project?: Uri, env?: { [key: string]: string }): string { - const substitutions = new Map(); - - const home = process.env.HOME || process.env.USERPROFILE; - if (home) { - substitutions.set('${userHome}', home); - } - - if (project) { - substitutions.set('${pythonProject}', project.fsPath); - } - - const ws = project ? workspace.getWorkspaceFolder(project) : undefined; - if (ws) { - substitutions.set('${workspaceFolder}', ws.uri.fsPath); - } - - substitutions.set('${cwd}', process.cwd()); - - (workspace.workspaceFolders ?? []).forEach((w) => { - substitutions.set('${workspaceFolder:' + w.name + '}', w.uri.fsPath); - }); - - const substEnv = env || process.env; - if (substEnv) { - for (const [key, value] of Object.entries(substEnv)) { - if (value && key.length > 0) { - substitutions.set('${env:' + key + '}', value); - } - } - } - - let result = value; - substitutions.forEach((v, k) => { - while (k.length > 0 && result.indexOf(k) >= 0) { - result = result.replace(k, v); - } - }); - - return result; -} diff --git a/src/extension.ts b/src/extension.ts index cb213d3..4144613 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,7 +1,7 @@ import semver from 'semver'; import { ExtensionContext, window } from 'vscode'; -import { registerLogger, traceInfo } from './common/logging'; +import { registerLogger } from './common/logging'; import { setPersistentState } from './common/persistentState'; import { PixiEnvManager } from './pixi/envManager'; import { PixiPackageManager } from './pixi/projectManager'; @@ -10,23 +10,17 @@ import { getEnvExtApi } from './pythonEnvsApi'; const MINIMUM_PIXI_VERSION = '0.53.0'; -export interface IDisposable { - dispose(): void | undefined | Promise; -} - export async function activate(context: ExtensionContext) { const api = await getEnvExtApi(); - const log = window.createOutputChannel('Pixi Environment Manager', { - log: true, - }); + const log = window.createOutputChannel('Pixi Environment Manager', { log: true }); context.subscriptions.push(log, registerLogger(log)); // Validate Pixi installation const stdout = await runPixi(['--version']); const versionMatch = stdout.trim().match(/^pixi (\d+\.\d+\.\d+)/); if (!versionMatch) { - const errorMsg = `Found invalid Pixi binary at ${getPixi()}.`; + const errorMsg = `Found invalid Pixi binary at ${await getPixi()}.`; window.showErrorMessage(errorMsg); throw new Error(errorMsg); } @@ -52,22 +46,3 @@ export async function activate(context: ExtensionContext) { const packageManager = new PixiPackageManager(api, log); context.subscriptions.push(api.registerPackageManager(packageManager)); } - -export async function disposeAll(disposables: IDisposable[]): Promise { - await Promise.all( - disposables.map(async (d) => { - try { - return Promise.resolve(d.dispose()); - } catch { - // do nothing - } - return Promise.resolve(); - }), - ); -} - -export async function deactivate(context: ExtensionContext) { - await disposeAll(context.subscriptions); - context.subscriptions.length = 0; // Clear subscriptions to prevent memory leaks - traceInfo('Pixi Environment Manager extension deactivated.'); -} diff --git a/src/pixi/envManager.ts b/src/pixi/envManager.ts index 6daf4e3..d49bb78 100644 --- a/src/pixi/envManager.ts +++ b/src/pixi/envManager.ts @@ -1,4 +1,3 @@ -import * as path from 'path'; import { EventEmitter, LogOutputChannel, MarkdownString, ProgressLocation, ThemeIcon, Uri, window } from 'vscode'; import { @@ -11,15 +10,14 @@ import { IconPath, PythonEnvironment, PythonEnvironmentApi, - PythonProject, RefreshEnvironmentsScope, ResolveEnvironmentContext, SetEnvironmentScope, } from '../api'; -import { getDefaultInterpreterPath } from '../common/defaultInterpreter'; import { createDeferred, Deferred } from '../common/deferred'; import { traceVerbose } from '../common/logging'; -import { EXTENSION_ID } from '../common/utils'; +import { resolvePixiProjectPaths } from '../common/searchPaths'; +import { PIXI_MANAGER_ID } from '../common/utils'; import { PixiEnvironment } from './types'; import { clearExtensionCache, @@ -32,14 +30,14 @@ import { export class PixiEnvManager implements EnvironmentManager { private globalEnv: PythonEnvironment | undefined; - private activeEnv: Map = new Map(); // Selected environment for each project - private projectToEnvs: Map = new Map(); // Maps a project path to its `pixi info` output + private activeEnv = new Map(); // Selected environment for each project + private projectToEnvs = new Map(); // Maps a project path to its `pixi info` output private readonly _onDidChangeEnvironment = new EventEmitter(); - public readonly onDidChangeEnvironment = this._onDidChangeEnvironment.event; + readonly onDidChangeEnvironment = this._onDidChangeEnvironment.event; private readonly _onDidChangeEnvironments = new EventEmitter(); - public readonly onDidChangeEnvironments = this._onDidChangeEnvironments.event; + readonly onDidChangeEnvironments = this._onDidChangeEnvironments.event; constructor( private readonly api: PythonEnvironmentApi, @@ -47,19 +45,21 @@ export class PixiEnvManager implements EnvironmentManager { ) { this.name = 'pixi'; this.displayName = 'Pixi'; - this.preferredPackageManagerId = `${EXTENSION_ID}:pixi`; + this.preferredPackageManagerId = PIXI_MANAGER_ID; this.tooltip = 'Pixi Environment Manager'; this.iconPath = new ThemeIcon('prefix-dev'); } - name: string; - displayName: string; - preferredPackageManagerId: string; - description?: string; - tooltip: string | MarkdownString; - iconPath?: IconPath; + readonly name: string; + readonly displayName: string; + readonly preferredPackageManagerId: string; + readonly description?: string; + readonly tooltip: string | MarkdownString; + readonly iconPath?: IconPath; - public dispose() { + dispose() { + this._onDidChangeEnvironment.dispose(); + this._onDidChangeEnvironments.dispose(); this.globalEnv = undefined; this.activeEnv.clear(); this.projectToEnvs.clear(); @@ -97,23 +97,14 @@ export class PixiEnvManager implements EnvironmentManager { await this.initialize(); if (scope === 'all') { - return [ - ...new Map( - Array.from(this.projectToEnvs.values()).flatMap((envs) => envs.map((env) => [env.envId.id, env])), - ).values(), - ]; + return [...this.buildEnvLookup().values()]; } if (scope instanceof Uri) { const project = this.api.getPythonProject(scope); - if (!project) { - return []; - } - - return this.projectToEnvs.get(project.uri.fsPath) || []; + return project ? this.projectToEnvs.get(project.uri.fsPath) || [] : []; } - // Skip 'global'. Pixi does not have global or base environments like Conda return []; } @@ -127,11 +118,7 @@ export class PixiEnvManager implements EnvironmentManager { } const project = this.api.getPythonProject(scope); - if (!project) { - return this.globalEnv; - } - - return this.activeEnv.get(project.uri.fsPath); + return project ? this.activeEnv.get(project.uri.fsPath) : this.globalEnv; } async set(scope: SetEnvironmentScope, environment?: PythonEnvironment) { @@ -144,19 +131,17 @@ export class PixiEnvManager implements EnvironmentManager { return; } - if (scope instanceof Uri) { - scope = [scope]; - } + const uris = scope instanceof Uri ? [scope] : scope; - scope.forEach(async (scope) => { - const project = this.api.getPythonProject(scope); + for (const uri of uris) { + const project = this.api.getPythonProject(uri); if (!project) { - return; + continue; } const projectPath = project.uri.fsPath; - const oldEnv = this.activeEnv.get(projectPath); + if (environment) { this.activeEnv.set(projectPath, environment); } else { @@ -165,7 +150,7 @@ export class PixiEnvManager implements EnvironmentManager { await setProjectEnvId(projectPath, environment?.envId.id); this.triggerDidChangeEnvironment(project.uri, oldEnv, environment); - }); + } } async resolve(context: ResolveEnvironmentContext): Promise { @@ -181,6 +166,26 @@ export class PixiEnvManager implements EnvironmentManager { await clearExtensionCache(); } + private buildEnvLookup(): Map { + return new Map( + Array.from(this.projectToEnvs.values()).flatMap((envs) => envs.map((env) => [env.envId.id, env])), + ); + } + + private diffEnvironments(oldEnvs: PixiEnvironment[], newEnvs: PixiEnvironment[]): DidChangeEnvironmentsEventArgs { + const oldIds = new Set(oldEnvs.map((e) => e.envId.id)); + const newIds = new Set(newEnvs.map((e) => e.envId.id)); + + return [ + ...oldEnvs + .filter((e) => !newIds.has(e.envId.id)) + .map((e) => ({ environment: e, kind: EnvironmentChangeKind.remove })), + ...newEnvs + .filter((e) => !oldIds.has(e.envId.id)) + .map((e) => ({ environment: e, kind: EnvironmentChangeKind.add })), + ]; + } + private async refreshAll(): Promise { await window.withProgress( { @@ -188,47 +193,35 @@ export class PixiEnvManager implements EnvironmentManager { title: 'Discovering Pixi environments', }, async () => { - const add: DidChangeEnvironmentsEventArgs = []; - const remove: DidChangeEnvironmentsEventArgs = []; - const oldProjectToEnvs = new Map(this.projectToEnvs); this.projectToEnvs.clear(); + // Collect project paths from registered Python projects and search paths const projects = this.api.getPythonProjects(); + const projectMap = new Map(projects.map((p) => [p.uri.fsPath, p])); - for (const project of projects) { - const projectPath = project.uri.fsPath; - - const newEnvs = await refreshPixi(projectPath); - const defaultEnvs = await this.getDefaultPathEnvironments(project); - newEnvs.push(...defaultEnvs); + const searchPathRoots = await resolvePixiProjectPaths(); + const projectPaths = new Set([...projectMap.keys(), ...searchPathRoots]); - const oldEnvs = oldProjectToEnvs.get(projectPath) || []; + const changes: DidChangeEnvironmentsEventArgs = []; - const oldEnvIds = new Set(oldEnvs.map((env) => env.envId.id)); - const newEnvIds = new Set(newEnvs.map((env) => env.envId.id)); + await Promise.all( + [...projectPaths].map(async (projectPath) => { + const oldEnvs = oldProjectToEnvs.get(projectPath) || []; + const newEnvs = await refreshPixi(projectPath); - oldEnvs - .filter((env) => !newEnvIds.has(env.envId.id)) - .forEach((env) => remove.push({ environment: env, kind: EnvironmentChangeKind.remove })); - - newEnvs - .filter((env) => !oldEnvIds.has(env.envId.id)) - .forEach((env) => add.push({ environment: env, kind: EnvironmentChangeKind.add })); - - this.projectToEnvs.set(projectPath, newEnvs); - } + changes.push(...this.diffEnvironments(oldEnvs, newEnvs)); + this.projectToEnvs.set(projectPath, newEnvs); + }), + ); - this._onDidChangeEnvironments.fire([...remove, ...add]); + this._onDidChangeEnvironments.fire(changes); - const envIdToEnv = new Map( - Array.from(this.projectToEnvs.values()).flatMap((envs) => envs.map((env) => [env.envId.id, env])), - ); + const envLookup = this.buildEnvLookup(); // Update global environment const globalEnvId = await getGlobalEnvId(); - const globalEnv = globalEnvId ? envIdToEnv.get(globalEnvId) : undefined; - + const globalEnv = globalEnvId ? envLookup.get(globalEnvId) : undefined; this.triggerDidChangeEnvironment(undefined, this.globalEnv, globalEnv); this.globalEnv = globalEnv; @@ -236,19 +229,19 @@ export class PixiEnvManager implements EnvironmentManager { const oldActiveEnv = new Map(this.activeEnv); this.activeEnv.clear(); - for (const project of projects) { - const projectPath = project.uri.fsPath; - + for (const projectPath of projectPaths) { const envId = await getProjectEnvId(projectPath); - let env = envId ? envIdToEnv.get(envId) : undefined; + const env = envId ? envLookup.get(envId) : undefined; if (env) { this.activeEnv.set(projectPath, env); - } else { - env = await this.trySetActiveFromDefault(project, projectPath); } - this.triggerDidChangeEnvironment(project.uri, oldActiveEnv.get(projectPath), env); + this.triggerDidChangeEnvironment( + projectMap.get(projectPath)?.uri, + oldActiveEnv.get(projectPath), + env, + ); } }, ); @@ -261,82 +254,24 @@ export class PixiEnvManager implements EnvironmentManager { } const projectPath = project.uri.fsPath; - const oldEnvs = this.projectToEnvs.get(projectPath) || []; const newEnvs = await refreshPixi(projectPath); - const defaultEnvs = await this.getDefaultPathEnvironments(project); - newEnvs.push(...defaultEnvs); - - const oldEnvIds = new Set(oldEnvs.map((env) => env.envId.id)); - const newEnvIds = new Set(newEnvs.map((env) => env.envId.id)); - - const add: DidChangeEnvironmentsEventArgs = []; - const remove: DidChangeEnvironmentsEventArgs = []; - - oldEnvs - .filter((env) => !newEnvIds.has(env.envId.id)) - .forEach((env) => remove.push({ environment: env, kind: EnvironmentChangeKind.remove })); - - newEnvs - .filter((env) => !oldEnvIds.has(env.envId.id)) - .forEach((env) => add.push({ environment: env, kind: EnvironmentChangeKind.add })); this.projectToEnvs.set(projectPath, newEnvs); - this._onDidChangeEnvironments.fire([...remove, ...add]); - - // Update the active environment for this project - const envIdToEnv = new Map( - Array.from(this.projectToEnvs.values()).flatMap((envs) => envs.map((env) => [env.envId.id, env])), - ); + this._onDidChangeEnvironments.fire(this.diffEnvironments(oldEnvs, newEnvs)); + // Update active environment for this project const envId = await getProjectEnvId(projectPath); - let env = envId ? envIdToEnv.get(envId) : undefined; + const env = envId ? newEnvs.find((e) => e.envId.id === envId) : undefined; this.triggerDidChangeEnvironment(project.uri, this.activeEnv.get(projectPath), env); if (env) { this.activeEnv.set(projectPath, env); } else { - env = await this.trySetActiveFromDefault(project, projectPath); + this.activeEnv.delete(projectPath); } } - private async getDefaultPathEnvironments(project: PythonProject): Promise { - const defaultInterpreterPath = getDefaultInterpreterPath(project); - - if (!defaultInterpreterPath) { - return []; - } - - const binPath = path.dirname(defaultInterpreterPath); - traceVerbose(`Also refreshing Pixi environments using defaultInterpreterPath: ${binPath}`); - return await refreshPixi(binPath); - } - - private async trySetActiveFromDefault( - project: PythonProject, - projectPath: string, - ): Promise { - const defaultInterpreterPath = getDefaultInterpreterPath(project); - - if (defaultInterpreterPath) { - const projectEnvs = this.projectToEnvs.get(projectPath) || []; - const matchingEnv = projectEnvs.find((env) => - defaultInterpreterPath.startsWith(env.environmentPath.fsPath), - ); - - if (matchingEnv) { - traceVerbose( - `Setting active environment for project ${projectPath} based on default interpreter path ${defaultInterpreterPath}`, - ); - this.activeEnv.set(projectPath, matchingEnv); - await setProjectEnvId(projectPath, matchingEnv.envId.id); - return matchingEnv; - } - } - - return undefined; - } - private triggerDidChangeEnvironment( uri: Uri | undefined, oldEnv: PythonEnvironment | undefined, diff --git a/src/pixi/projectManager.ts b/src/pixi/projectManager.ts index 1dfdc1f..e14f8bd 100644 --- a/src/pixi/projectManager.ts +++ b/src/pixi/projectManager.ts @@ -21,8 +21,8 @@ import { PythonEnvironmentApi, } from '../api'; import { traceVerbose } from '../common/logging'; -import { PixiEnvironment, PixiPackage } from './types'; -import { pixiPkgsToPackages, runPixi } from './utils'; +import { PixiEnvironment } from './types'; +import { listPixiPackages, pixiPkgsToPackages } from './utils'; export class PixiPackageManager implements PackageManager, Disposable { private readonly _onDidChangePackages = new EventEmitter(); @@ -71,16 +71,8 @@ export class PixiPackageManager implements PackageManager, Disposable { return; } - const manifest_path = environment.pixiInfo.project_info.manifest_path; - const project_path = path.dirname(manifest_path); - - const stdout = await runPixi( - ['list', '--no-install', '--frozen', '--json', '--environment', environment.name], - { - cwd: project_path, - }, - ); - const pixiPackages: PixiPackage[] = JSON.parse(stdout); + const projectPath = path.dirname(environment.pixiInfo.project_info.manifest_path); + const pixiPackages = await listPixiPackages(environment.name, projectPath); const before = environment.packages; const after = pixiPkgsToPackages(pixiPackages, environment.envId.id); @@ -101,32 +93,30 @@ export class PixiPackageManager implements PackageManager, Disposable { const changes: { kind: PackageChangeKind; pkg: Package }[] = []; // Find removed packages - for (const beforePkg of before) { - const found = after.find((p) => p.name === beforePkg.name); - if (!found) { - changes.push({ kind: PackageChangeKind.remove, pkg: beforePkg }); + const beforeByName = new Map(before.map((p) => [p.name, p])); + const afterByName = new Map(after.map((p) => [p.name, p])); + + for (const pkg of before) { + if (!afterByName.has(pkg.name)) { + changes.push({ kind: PackageChangeKind.remove, pkg }); } } // Find added and updated packages - for (const afterPkg of after) { - const beforePkg = before.find((p) => p.name === afterPkg.name); - if (!beforePkg) { + for (const pkg of after) { + const prev = beforeByName.get(pkg.name); + if (!prev) { // Package was added - changes.push({ kind: PackageChangeKind.add, pkg: afterPkg }); - } else if (beforePkg.version !== afterPkg.version) { + changes.push({ kind: PackageChangeKind.add, pkg }); + } else if (prev.version !== pkg.version) { // Package version changed - treat as remove then add - changes.push({ kind: PackageChangeKind.remove, pkg: beforePkg }); - changes.push({ kind: PackageChangeKind.add, pkg: afterPkg }); + changes.push({ kind: PackageChangeKind.remove, pkg: prev }); + changes.push({ kind: PackageChangeKind.add, pkg }); } } if (changes.length > 0) { - this._onDidChangePackages.fire({ - environment, - manager: this, - changes, - }); + this._onDidChangePackages.fire({ environment, manager: this, changes }); } } } diff --git a/src/pixi/utils.ts b/src/pixi/utils.ts index 68a9d4e..42dfc3c 100644 --- a/src/pixi/utils.ts +++ b/src/pixi/utils.ts @@ -1,5 +1,4 @@ import * as ch from 'child_process'; -import * as fs from 'fs'; import { CancellationError, CancellationToken, Uri, window, workspace } from 'vscode'; import which from 'which'; @@ -9,13 +8,13 @@ import { quoteArgs } from '../common/execUtils'; import { findPythonExecutable } from '../common/findPython'; import { traceError, traceInfo, traceVerbose } from '../common/logging'; import { getWorkspacePersistentState } from '../common/persistentState'; -import { EXTENSION_ID, untildify } from '../common/utils'; +import { PIXI_MANAGER_ID, untildify } from '../common/utils'; import { PixiEnvironment, PixiInfo, PixiPackage } from './types'; -export const PIXI_WORKSPACE_KEY = `${EXTENSION_ID}:pixi:WORKSPACE_SELECTED`; -export const PIXI_GLOBAL_KEY = `${EXTENSION_ID}:pixi:GLOBAL_SELECTED`; +const PIXI_WORKSPACE_KEY = `${PIXI_MANAGER_ID}:WORKSPACE_SELECTED`; +const PIXI_GLOBAL_KEY = `${PIXI_MANAGER_ID}:GLOBAL_SELECTED`; -export async function findPixi(): Promise { +async function findPixi(): Promise { try { return await which('pixi'); } catch { @@ -24,20 +23,21 @@ export async function findPixi(): Promise { } export async function getPixi(): Promise { - const config = workspace.getConfiguration('pixi'); - const value = config.get('executablePath'); - - if (!value || typeof value !== 'string') { - const pixiPath = await findPixi(); - if (!pixiPath) { - const errorMsg = - 'Pixi executable not found. Please install Pixi or set "pixi-code.pixiExecutable" in your settings.'; - window.showErrorMessage(errorMsg); - throw new Error(errorMsg); - } - return pixiPath; + const config = workspace.getConfiguration('pixi-code'); + const value = config.get('pixiExecutable'); + + if (value) { + return untildify(value); + } + + const pixiPath = await findPixi(); + if (!pixiPath) { + const errorMsg = + 'Pixi executable not found. Please install Pixi or set "pixi-code.pixiExecutable" in your settings.'; + window.showErrorMessage(errorMsg); + throw new Error(errorMsg); } - return untildify(value); + return pixiPath; } async function _runPixi( @@ -48,33 +48,37 @@ async function _runPixi( ): Promise { const deferred = createDeferred(); args = quoteArgs(args); - const proc = ch.spawn(pixi, args, { - shell: true, - ...options, - }); + const proc = ch.spawn(pixi, args, { shell: true, ...options }); - token?.onCancellationRequested(() => { + const cancelDisposable = token?.onCancellationRequested(() => { proc.kill(); deferred.reject(new CancellationError()); }); let stdout = ''; let stderr = ''; + let exitCode: number | null = null; + proc.stdout?.on('data', (data) => { - const d = data.toString('utf-8'); - stdout += d; + stdout += data.toString('utf-8'); }); proc.stderr?.on('data', (data) => { const d = data.toString('utf-8'); stderr += d; traceError(d.trim()); }); - proc.on('close', () => { - deferred.resolve(stdout); + proc.on('error', (err) => { + deferred.reject(err); }); proc.on('exit', (code) => { - if (code !== 0) { + exitCode = code; + }); + proc.on('close', () => { + cancelDisposable?.dispose(); + if (exitCode !== 0) { deferred.reject(new Error(`Failed to run "pixi ${args.join(' ')}":\n ${stderr}`)); + } else { + deferred.resolve(stdout); } }); @@ -83,92 +87,76 @@ async function _runPixi( export async function runPixi(args: string[], options?: ch.SpawnOptions, token?: CancellationToken): Promise { const pixi = await getPixi(); - return await _runPixi(pixi, args, options, token); + return _runPixi(pixi, args, options, token); } -export async function refreshPixi(project_path: string): Promise { - try { - if (!fs.existsSync(project_path)) { - traceVerbose(`Project path does not exist: ${project_path}`); - return []; - } +export async function listPixiPackages(envName: string, projectPath: string): Promise { + const stdout = await runPixi(['list', '--no-install', '--frozen', '--json', '--environment', envName], { + cwd: projectPath, + }); + return JSON.parse(stdout); +} +export async function refreshPixi(projectPath: string): Promise { + try { const pixi = await getPixi(); - const environments: PixiEnvironment[] = []; - - const stdout = await runPixi(['info', '--json'], { cwd: project_path }); + const stdout = await _runPixi(pixi, ['info', '--json'], { cwd: projectPath }); const pixiInfo: PixiInfo = JSON.parse(stdout); if (!pixiInfo.project_info) { - traceVerbose(`No project info found for Pixi project at ${project_path}`); + traceVerbose(`No project info found for Pixi project at ${projectPath}`); return []; } const projectName = pixiInfo.project_info.name; const manifestPath = pixiInfo.project_info.manifest_path; - for (const pixiEnv of pixiInfo.environments_info) { - const stdout = await runPixi( - ['list', '--no-install', '--frozen', '--json', '--environment', pixiEnv.name], - { - cwd: project_path, - }, - ); - const pixiPackages: PixiPackage[] = JSON.parse(stdout); - const pythonPackage = pixiPackages.find((pkg) => pkg.name === 'python'); - - // Skip environments without Python - if (!pythonPackage) { - continue; - } - - // If the environment is not installed, do not skip it. - // Both `pixi info` and `pixi list` work fine with an environment that is not installed, and we want to take - // advantage of that. Besides, `pythonExecutable` isn't really used, since we provide both `activatedRun` - // and `activation` commands. - const pythonExecutable = (await findPythonExecutable(pixiEnv.prefix)) || ''; - - const env: PixiEnvironment = { - name: pixiEnv.name, - displayName: pixiEnv.name, - shortDisplayName: pixiEnv.name, - displayPath: pixiEnv.prefix, - version: pythonPackage.version, - environmentPath: Uri.file(pixiEnv.prefix), - description: `Python ${pythonPackage.version}`, - execInfo: { - run: { executable: pythonExecutable }, - activatedRun: { - executable: pythonExecutable, - args: [], - }, - activation: [ - { + const results = await Promise.all( + pixiInfo.environments_info.map(async (pixiEnv) => { + const pixiPackages = await listPixiPackages(pixiEnv.name, projectPath); + const pythonPackage = pixiPackages.find((pkg) => pkg.name === 'python'); + + if (!pythonPackage) { + return null; + } + + const pythonExecutable = (await findPythonExecutable(pixiEnv.prefix)) || ''; + + return { + name: pixiEnv.name, + displayName: pixiEnv.name, + shortDisplayName: pixiEnv.name, + displayPath: pixiEnv.prefix, + version: pythonPackage.version, + environmentPath: Uri.file(pixiEnv.prefix), + description: `Python ${pythonPackage.version}`, + execInfo: { + run: { executable: pythonExecutable }, + activatedRun: { executable: pixi, - args: ['shell', '--manifest-path', manifestPath, '-e', pixiEnv.name], - }, - ], - deactivation: [ - { - executable: 'exit', - args: [], + args: ['run', '--manifest-path', manifestPath, '-e', pixiEnv.name, 'python'], }, - ], - }, - sysPrefix: pixiEnv.prefix, - group: projectName, - envId: { - id: pixiEnv.prefix, - managerId: `${EXTENSION_ID}:pixi`, - }, - pixiInfo, - packages: pixiPkgsToPackages(pixiPackages, pixiEnv.prefix), - }; - - environments.push(env); - } + activation: [ + { + executable: pixi, + args: ['shell', '--manifest-path', manifestPath, '-e', pixiEnv.name], + }, + ], + deactivation: [{ executable: 'exit', args: [] }], + }, + sysPrefix: pixiEnv.prefix, + group: projectName, + envId: { + id: pixiEnv.prefix, + managerId: PIXI_MANAGER_ID, + }, + pixiInfo, + packages: pixiPkgsToPackages(pixiPackages, pixiEnv.prefix), + } as PixiEnvironment; + }), + ); - return environments; + return results.filter((env): env is PixiEnvironment => env !== null); } catch (error) { traceInfo(`Failed to get pixi environments: ${error}`); return []; @@ -185,20 +173,19 @@ export function pixiPkgsToPackages(pixiPackages: PixiPackage[], environmentId: s version: pkg.version, pkgId: { id: pkg.name, - managerId: `${EXTENSION_ID}:pixi`, + managerId: PIXI_MANAGER_ID, environmentId, }, })); } -export type PixiPersistentState = { - [projectPath: string]: string; // Maps project paths to Pixi prefixes +type PixiPersistentState = { + [projectPath: string]: string; }; export async function clearExtensionCache() { - const keys = [PIXI_WORKSPACE_KEY, PIXI_GLOBAL_KEY]; const state = await getWorkspacePersistentState(); - await state.clear(keys); + await state.clear([PIXI_WORKSPACE_KEY, PIXI_GLOBAL_KEY]); } export async function getGlobalEnvId(): Promise { diff --git a/tsconfig.json b/tsconfig.json index c741ab1..4fb4b92 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "noImplicitAny": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "skipLibCheck": true } }