From 232a1af4e6d9bd9252562384f20b1a405c52ab7c Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:27:00 +0100 Subject: [PATCH 01/13] Better python utilization in stub switcher Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- src/activator.mts | 3 +- src/stubs.mts | 85 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/activator.mts b/src/activator.mts index c046805..0101c23 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -1547,7 +1547,8 @@ export default class Activator { version.includes(" - ") ? displayStringToStubPort(versionParts[0]) : versionParts[0], - this.settings! + this.settings!, + this.pythonPath ); if (result) { diff --git a/src/stubs.mts b/src/stubs.mts index ad911c5..007de17 100644 --- a/src/stubs.mts +++ b/src/stubs.mts @@ -286,51 +286,84 @@ export function displayStringToStubPort(displayString: string): string { export async function installStubsByVersion( version: string, port: string, - settings: Settings + settings: Settings, + pythonPath?: string ): Promise { - const pip3: string | null = await which("pip3", { nothrow: true }); - // check if pip is available - const pip: string | null = await which("pip", { nothrow: true }); - let command = ""; - // if not available check for python prefixed installations - if (pip3 === null && pip === null) { - const python3: string | null = await which("python3", { nothrow: true }); - // windows py launcher - const py: string | null = await which("py", { nothrow: true }); + const isWin = process.platform === "win32"; - // if (py ?? python) -m pip returns sth containing "No module named" -> not installed + if (pythonPath) { + command = `"${pythonPath}" -m pip`; - const pyCmd = python3 ?? py; - if (pyCmd !== null) { - const result = execSync(pyCmd + " -m pip"); + try { + const result = execSync(`${isWin ? "&" : ""}${command}`, { + windowsHide: true, + shell: process.platform === "win32" ? "powershell" : undefined, + }); if (result.toString("utf-8").toLowerCase().includes("no module named")) { + void window.showWarningMessage( + "The selected python interpreter does not have pip installed." + ); + command = ""; + } + } catch (error) { + console.log(error); + void window.showErrorMessage( + "python3 or py (with pip) is required (in PATH) to install" + + " stubs different from the included ones." + ); + command = ""; + } + } + + if (command.length <= 0) { + const pip3: string | null = await which("pip3", { nothrow: true }); + // check if pip is available + const pip: string | null = await which("pip", { nothrow: true }); + + // if not available check for python prefixed installations + if (pip3 === null && pip === null) { + const python3: string | null = await which("python3", { nothrow: true }); + // windows py launcher + const py: string | null = await which("py", { nothrow: true }); + + // if (py ?? python) -m pip returns sth containing "No module named" -> not installed + + const pyCmd = python3 ?? py; + if (pyCmd !== null) { + const result = execSync(`${isWin ? "&" : ""}"${pyCmd}" -m pip`, { + windowsHide: true, + shell: process.platform === "win32" ? "powershell" : undefined, + }); + if ( + result.toString("utf-8").toLowerCase().includes("no module named") + ) { + void window.showErrorMessage( + `pip module is required (in ${pyCmd}) to install` + + " stubs different from the included ones." + ); + + return false; + } + command = `"${pyCmd}" -m pip`; + } else { void window.showErrorMessage( - `pip module is required (in ${pyCmd}) to install` + + "python3 or py is required (in PATH) to install" + " stubs different from the included ones." ); return false; } - command = `"${pyCmd}" -m pip`; } else { - void window.showErrorMessage( - "python3 or py is required (in PATH) to install" + - " stubs different from the included ones." - ); - - return false; + assert(pip3 !== null || pip !== null); + command = `"${(pip3 ?? pip)!}"`; } - } else { - assert(pip3 !== null || pip !== null); - command = `"${(pip3 ?? pip)!}"`; } const folderName = `${port}==${version}`; const target = getStubsPathForVersionPosix(folderName); mkdirpSync(target); - const isWin = process.platform === "win32"; // install stubs with pip vscode user directory const result = execSync( `${isWin ? "&" : ""}${command} install ${port}==${version} ` + From df9b2944fe56d64102f95fc222eb621017dfa699 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 02:57:00 +0100 Subject: [PATCH 02/13] Update dependencies + Fix #254, Upgrade to pico-mpy-com v1.0.20 Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package-lock.json | 689 ++++++++++++++++++++++------------------------ package.json | 32 +-- 2 files changed, 347 insertions(+), 374 deletions(-) diff --git a/package-lock.json b/package-lock.json index 19399ae..edbf38f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,40 +20,40 @@ "linux" ], "dependencies": { - "@paulober/pico-mpy-com": "^1.0.19", + "@paulober/pico-mpy-com": "^1.0.20", "@vscode/python-extension": "^1.0.5", "axios": "^1.7.7", "fs-extra": "^11.2.0", "lodash": "^4.17.21", "rimraf": "^6.0.1", - "undici": "^6.19.8", - "uuid": "^10.0.0", - "which": "^4.0.0" + "undici": "^6.21.0", + "uuid": "^11.0.3", + "which": "^5.0.0" }, "devDependencies": { - "@eslint/js": "^9.10.0", - "@rollup/plugin-commonjs": "^26.0.1", + "@eslint/js": "^9.15.0", + "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-terser": "^0.4.4", - "@rollup/plugin-typescript": "^11.1.6", + "@rollup/plugin-typescript": "^12.1.1", "@serialport/bindings-cpp": "^12.0.1", "@types/eslint": "^9.6.1", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.7", - "@types/node": "^20.14.0", + "@types/lodash": "^4.17.13", + "@types/node": "^20.14", "@types/uuid": "^10.0.0", "@types/vscode": "^1.92.0", "@types/which": "^3.0.4", "@vscode/test-electron": "^2.4.1", - "eslint": "^9.10.0", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "patch-package": "^8.0.0", - "rollup": "^4.22.4", + "rollup": "^4.27.2", "rollup-plugin-copy": "^3.5.0", - "tslib": "^2.7.0", - "typescript": "^5.6.2", - "typescript-eslint": "^8.5.0" + "tslib": "^2.8.1", + "typescript": "^5.6.3", + "typescript-eslint": "^8.14.0" }, "engines": { "node": ">=20.14.0", @@ -90,9 +90,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "license": "MIT", "engines": { @@ -100,9 +100,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.0.tgz", + "integrity": "sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -114,10 +114,20 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/core": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.0.tgz", + "integrity": "sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -139,9 +149,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.10.0.tgz", - "integrity": "sha512-fuXtbiP5GWIn8Fz+LWoOMVf/Jxm+aajZYkhi6CuEm4SxymFM+eUWzbO9qXT+L0iCkL5+KGYMCSGxo686H19S1g==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.15.0.tgz", + "integrity": "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg==", "dev": true, "license": "MIT", "engines": { @@ -159,9 +169,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.1.0.tgz", - "integrity": "sha512-autAXT203ixhqei9xt+qkYOvY8l6LAFIdT2UXc/RPNeUVfqRF1BV94GTJyVPFKT8nFM6MyVJhjLj9E8JWvf5zQ==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -171,6 +181,44 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -186,9 +234,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", - "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -346,9 +394,9 @@ } }, "node_modules/@paulober/pico-mpy-com": { - "version": "1.0.19", - "resolved": "https://npm.pkg.github.com/download/@paulober/pico-mpy-com/1.0.19/dafe9943c0ea2ea58e205803fce4bf29d14ab6a7", - "integrity": "sha512-auc+kjW7UCHWvQHmIW36UqEVfRKinoo0yW1fgNeviiHZ0J7DUq4JoTfJNmtO/dfUQKI3OgCVjoNK507zJRGlNw==", + "version": "1.0.20", + "resolved": "https://npm.pkg.github.com/download/@paulober/pico-mpy-com/1.0.20/0a10e7e473b664b1ec0c455a3d35612452ed89a8", + "integrity": "sha512-6+VcEJr8V7XRr7M1cuZNjDUDuOZcWj9ixyj5d4k0sT6lDaxwgH23Tjv8Asx4mvZqsBzw3wxpDf6q5lYYW0lDcA==", "cpu": [ "x64", "arm64" @@ -378,18 +426,19 @@ } }, "node_modules/@rollup/plugin-commonjs": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", - "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", + "version": "28.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.1.tgz", + "integrity": "sha512-+tNWdlWKbpB3WgBN7ijjYkq9X5uhjmcvyjEght4NmH5fAU++zfQzAJ6wumLS+dNcvwEZhKx2Z+skY8m7v0wGSA==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", - "glob": "^10.4.1", + "fdir": "^6.2.0", "is-reference": "1.2.1", - "magic-string": "^0.30.3" + "magic-string": "^0.30.3", + "picomatch": "^4.0.2" }, "engines": { "node": ">=16.0.0 || 14 >= 14.17" @@ -403,6 +452,34 @@ } } }, + "node_modules/@rollup/plugin-commonjs/node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/plugin-json": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", @@ -425,16 +502,15 @@ } }, "node_modules/@rollup/plugin-node-resolve": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz", - "integrity": "sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.0.tgz", + "integrity": "sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", - "is-builtin-module": "^3.2.1", "is-module": "^1.0.0", "resolve": "^1.22.1" }, @@ -474,9 +550,9 @@ } }, "node_modules/@rollup/plugin-typescript": { - "version": "11.1.6", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.6.tgz", - "integrity": "sha512-R92yOmIACgYdJ7dJ97p4K69I8gg6IEHt8M7dUBxN3W6nrO8uUxX5ixl0yU/N3aZTi8WhPuICvOHXQvF6FaykAA==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.1.tgz", + "integrity": "sha512-t7O653DpfB5MbFrqPe/VcKFFkvRuFNp9qId3xq4Eth5xlyymzxNpye2z8Hrl0RIMuXTSr5GGcFpkdlMeacUiFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -524,9 +600,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.2.tgz", + "integrity": "sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==", "cpu": [ "arm" ], @@ -538,9 +614,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.2.tgz", + "integrity": "sha512-xsPeJgh2ThBpUqlLgRfiVYBEf/P1nWlWvReG+aBWfNv3XEBpa6ZCmxSVnxJgLgkNz4IbxpLy64h2gCmAAQLneQ==", "cpu": [ "arm64" ], @@ -552,9 +628,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.2.tgz", + "integrity": "sha512-KnXU4m9MywuZFedL35Z3PuwiTSn/yqRIhrEA9j+7OSkji39NzVkgxuxTYg5F8ryGysq4iFADaU5osSizMXhU2A==", "cpu": [ "arm64" ], @@ -566,9 +642,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.2.tgz", + "integrity": "sha512-Hj77A3yTvUeCIx/Vi+4d4IbYhyTwtHj07lVzUgpUq9YpJSEiGJj4vXMKwzJ3w5zp5v3PFvpJNgc/J31smZey6g==", "cpu": [ "x64" ], @@ -579,10 +655,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.2.tgz", + "integrity": "sha512-RjgKf5C3xbn8gxvCm5VgKZ4nn0pRAIe90J0/fdHUsgztd3+Zesb2lm2+r6uX4prV2eUByuxJNdt647/1KPRq5g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.2.tgz", + "integrity": "sha512-duq21FoXwQtuws+V9H6UZ+eCBc7fxSpMK1GQINKn3fAyd9DFYKPJNcUhdIKOrMFjLEJgQskoMoiuizMt+dl20g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.2.tgz", + "integrity": "sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==", "cpu": [ "arm" ], @@ -594,9 +698,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.2.tgz", + "integrity": "sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==", "cpu": [ "arm" ], @@ -608,9 +712,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.2.tgz", + "integrity": "sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==", "cpu": [ "arm64" ], @@ -622,9 +726,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.2.tgz", + "integrity": "sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==", "cpu": [ "arm64" ], @@ -636,9 +740,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.2.tgz", + "integrity": "sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==", "cpu": [ "ppc64" ], @@ -650,9 +754,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.2.tgz", + "integrity": "sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==", "cpu": [ "riscv64" ], @@ -664,9 +768,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.2.tgz", + "integrity": "sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==", "cpu": [ "s390x" ], @@ -678,9 +782,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.2.tgz", + "integrity": "sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==", "cpu": [ "x64" ], @@ -692,9 +796,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.2.tgz", + "integrity": "sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==", "cpu": [ "x64" ], @@ -706,9 +810,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.2.tgz", + "integrity": "sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==", "cpu": [ "arm64" ], @@ -720,9 +824,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.2.tgz", + "integrity": "sha512-RsnE6LQkUHlkC10RKngtHNLxb7scFykEbEwOFDjr3CeCMG+Rr+cKqlkKc2/wJ1u4u990urRHCbjz31x84PBrSQ==", "cpu": [ "ia32" ], @@ -734,9 +838,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.2.tgz", + "integrity": "sha512-foJM5vv+z2KQmn7emYdDLyTbkoO5bkHZE1oth2tWbQNGW7mX32d46Hz6T0MqXdWS2vBZhaEtHqdy9WYwGfiliA==", "cpu": [ "x64" ], @@ -937,9 +1041,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, @@ -983,9 +1087,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", - "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg==", "dev": true, "license": "MIT" }, @@ -1035,17 +1139,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.5.0.tgz", - "integrity": "sha512-lHS5hvz33iUFQKuPFGheAB84LwcJ60G8vKnEhnfcK1l8kGVLro2SFYW6K0/tj8FUhRJ0VHyg1oAfg50QGbPPHw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", + "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/type-utils": "8.5.0", - "@typescript-eslint/utils": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/type-utils": "8.14.0", + "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1069,16 +1173,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.5.0.tgz", - "integrity": "sha512-gF77eNv0Xz2UJg/NbpWJ0kqAm35UMsvZf1GHj8D9MRFTj/V3tAciIWXfmPLsAAF/vUlpWPvUDyH1jjsr0cMVWw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", + "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4" }, "engines": { @@ -1098,14 +1202,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.5.0.tgz", - "integrity": "sha512-06JOQ9Qgj33yvBEx6tpC8ecP9o860rsR22hWMEd12WcTRrfaFgHr2RB/CA/B+7BMhHkXT4chg2MyboGdFGawYg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", + "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0" + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1116,14 +1220,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.5.0.tgz", - "integrity": "sha512-N1K8Ix+lUM+cIDhL2uekVn/ZD7TZW+9/rwz8DclQpcQ9rk4sIL5CAlBC0CugWKREmDjBzI/kQqU4wkg46jWLYA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", + "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.5.0", - "@typescript-eslint/utils": "8.5.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/utils": "8.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -1141,9 +1245,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.5.0.tgz", - "integrity": "sha512-qjkormnQS5wF9pjSi6q60bKUHH44j2APxfh9TQRXK8wbYVeDYYdYJGIROL87LGZZ2gz3Rbmjc736qyL8deVtdw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", + "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", "dev": true, "license": "MIT", "engines": { @@ -1155,14 +1259,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.5.0.tgz", - "integrity": "sha512-vEG2Sf9P8BPQ+d0pxdfndw3xIXaoSjliG0/Ejk7UggByZPKXmJmw3GW5jV2gHNQNawBUyfahoSiCFVov0Ruf7Q==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", + "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/visitor-keys": "8.5.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -1210,16 +1314,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.5.0.tgz", - "integrity": "sha512-6yyGYVL0e+VzGYp60wvkBHiqDWOpT63pdMV2CVG4LVDd5uR6q1qQN/7LafBZtAtNIn/mqXjsSeS5ggv/P0iECw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", + "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.5.0", - "@typescript-eslint/types": "8.5.0", - "@typescript-eslint/typescript-estree": "8.5.0" + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1233,13 +1337,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.5.0.tgz", - "integrity": "sha512-yTPqMnbAZJNy2Xq2XU8AdtOW9tJIr+UQb64aXB9f3B1498Zx9JorVgFJcZpEc9UBuCCrdzKID2RGAMkYcDtZOw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", + "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.5.0", + "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -1298,9 +1402,9 @@ "license": "BSD-2-Clause" }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -1528,19 +1632,6 @@ "dev": true, "license": "MIT" }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -1699,9 +1790,9 @@ "license": "MIT" }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", + "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -1856,29 +1947,32 @@ } }, "node_modules/eslint": { - "version": "9.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.10.0.tgz", - "integrity": "sha512-Y4D0IgtBZfOcOUAIQTSXBKoNGfY0REGqHJG6+Q81vNippW5YlKjHFj4soMxamKK1NXHUWuBZTLdU3Km+L/pcHw==", + "version": "9.15.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.15.0.tgz", + "integrity": "sha512-7CrWySmIibCgT1Os28lUU6upBshZ+GxybLOrmRzi08kS8MBuO8QA7pXEgYgY5W8vK3e74xv0lpjo9DbaGU9Rkw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", - "@eslint/config-array": "^0.18.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.10.0", - "@eslint/plugin-kit": "^0.1.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.15.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.0", - "@nodelib/fs.walk": "^1.2.8", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.0.2", - "eslint-visitor-keys": "^4.0.0", - "espree": "^10.1.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -1888,14 +1982,11 @@ "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -1929,9 +2020,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", - "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -1946,9 +2037,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", - "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1959,15 +2050,15 @@ } }, "node_modules/espree": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", - "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.0.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2280,27 +2371,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2314,32 +2384,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/globals": { "version": "14.0.0", "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", @@ -2595,22 +2639,6 @@ "dev": true, "license": "ISC" }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -2705,16 +2733,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-plain-object": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", @@ -2777,22 +2795,6 @@ "node": ">=16" } }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2991,13 +2993,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, "node_modules/magic-string": { "version": "0.30.11", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", @@ -3484,23 +3479,6 @@ "dev": true, "license": "MIT" }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -3777,13 +3755,13 @@ } }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.27.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.2.tgz", + "integrity": "sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -3793,22 +3771,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.27.2", + "@rollup/rollup-android-arm64": "4.27.2", + "@rollup/rollup-darwin-arm64": "4.27.2", + "@rollup/rollup-darwin-x64": "4.27.2", + "@rollup/rollup-freebsd-arm64": "4.27.2", + "@rollup/rollup-freebsd-x64": "4.27.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.2", + "@rollup/rollup-linux-arm-musleabihf": "4.27.2", + "@rollup/rollup-linux-arm64-gnu": "4.27.2", + "@rollup/rollup-linux-arm64-musl": "4.27.2", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.2", + "@rollup/rollup-linux-riscv64-gnu": "4.27.2", + "@rollup/rollup-linux-s390x-gnu": "4.27.2", + "@rollup/rollup-linux-x64-gnu": "4.27.2", + "@rollup/rollup-linux-x64-musl": "4.27.2", + "@rollup/rollup-win32-arm64-msvc": "4.27.2", + "@rollup/rollup-win32-ia32-msvc": "4.27.2", + "@rollup/rollup-win32-x64-msvc": "4.27.2", "fsevents": "~2.3.2" } }, @@ -4253,13 +4233,6 @@ "node": ">=10" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -4287,9 +4260,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", + "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", "dev": true, "license": "MIT", "engines": { @@ -4300,9 +4273,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, @@ -4320,9 +4293,9 @@ } }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4334,15 +4307,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.5.0.tgz", - "integrity": "sha512-uD+XxEoSIvqtm4KE97etm32Tn5MfaZWgWfMMREStLxR6JzvHkc2Tkj7zhTEK5XmtpTmKHNnG8Sot6qDfhHtR1Q==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", + "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.5.0", - "@typescript-eslint/parser": "8.5.0", - "@typescript-eslint/utils": "8.5.0" + "@typescript-eslint/eslint-plugin": "8.14.0", + "@typescript-eslint/parser": "8.14.0", + "@typescript-eslint/utils": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4358,9 +4331,9 @@ } }, "node_modules/undici": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.8.tgz", - "integrity": "sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz", + "integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==", "license": "MIT", "engines": { "node": ">=18.17" @@ -4400,22 +4373,22 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "license": "ISC", "dependencies": { "isexe": "^3.1.1" @@ -4424,7 +4397,7 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/word-wrap": { diff --git a/package.json b/package.json index 101c714..541dcc3 100644 --- a/package.json +++ b/package.json @@ -619,7 +619,7 @@ "scripts": { "vscode:uninstall": "node ./dist/vscodeUninstall.mjs", "vscode:prepublish": "npm run package", - "postinstall": "patch-package && python -m pip install -U micropython-rp2-rpi_pico_w-stubs==1.23.* --target ./mpy_stubs --no-user", + "postinstall": "patch-package && python3 -m pip install -U micropython-rp2-rpi_pico_w-stubs==1.23.* --target ./mpy_stubs --no-user", "compile-uninstaller": "rollup -c uninstall.rollup.config.mjs --environment BUILD:production", "compile": "rollup -c && npm run compile-uninstaller", "watch": "rollup -cw", @@ -632,40 +632,40 @@ "test": "node ./out/test/runTest.js" }, "devDependencies": { - "@eslint/js": "^9.10.0", - "@rollup/plugin-commonjs": "^26.0.1", + "@eslint/js": "^9.15.0", + "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-terser": "^0.4.4", - "@rollup/plugin-typescript": "^11.1.6", + "@rollup/plugin-typescript": "^12.1.1", "@serialport/bindings-cpp": "^12.0.1", "@types/eslint": "^9.6.1", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.7", - "@types/node": "^20.14.0", + "@types/lodash": "^4.17.13", + "@types/node": "^20.14", "@types/uuid": "^10.0.0", "@types/vscode": "^1.92.0", "@types/which": "^3.0.4", "@vscode/test-electron": "^2.4.1", - "eslint": "^9.10.0", + "eslint": "^9.15.0", "eslint-config-prettier": "^9.1.0", "patch-package": "^8.0.0", - "rollup": "^4.22.4", + "rollup": "^4.27.2", "rollup-plugin-copy": "^3.5.0", - "tslib": "^2.7.0", - "typescript": "^5.6.2", - "typescript-eslint": "^8.5.0" + "tslib": "^2.8.1", + "typescript": "^5.6.3", + "typescript-eslint": "^8.14.0" }, "dependencies": { - "@paulober/pico-mpy-com": "^1.0.19", + "@paulober/pico-mpy-com": "^1.0.20", "@vscode/python-extension": "^1.0.5", "axios": "^1.7.7", "fs-extra": "^11.2.0", "lodash": "^4.17.21", "rimraf": "^6.0.1", - "undici": "^6.19.8", - "uuid": "^10.0.0", - "which": "^4.0.0" + "undici": "^6.21.0", + "uuid": "^11.0.3", + "which": "^5.0.0" }, "packageManager": "npm@10.8.3+sha512.d08425c8062f56d43bb8e84315864218af2492eb769e1f1ca40740f44e85bd148969382d651660363942e5909cb7ffcbef7ca0ae963ddc2c57a51243b4da8f56" } From 1fdaebe0128c1de29ddc7a085a5a3740753548a2 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 15:43:53 +0100 Subject: [PATCH 03/13] Added clean+restore behaviour Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package.json | 3 +- src/activator.mts | 30 +++---- src/terminal.mts | 219 +++++++++++++++++++++++++++++----------------- 3 files changed, 152 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index 541dcc3..7d85aea 100644 --- a/package.json +++ b/package.json @@ -620,9 +620,10 @@ "vscode:uninstall": "node ./dist/vscodeUninstall.mjs", "vscode:prepublish": "npm run package", "postinstall": "patch-package && python3 -m pip install -U micropython-rp2-rpi_pico_w-stubs==1.23.* --target ./mpy_stubs --no-user", + "cp-prebuilds": "cp -r node_modules/@serialport/bindings-cpp/prebuilds ./prebuilds", "compile-uninstaller": "rollup -c uninstall.rollup.config.mjs --environment BUILD:production", "compile": "rollup -c && npm run compile-uninstaller", - "watch": "rollup -cw", + "watch": "npm run cp-prebuilds && rollup -cw", "package-local": "rimraf dist && rollup -c --environment BUILD:production --sourcemap hidden && npm run compile-uninstaller", "package": "rollup -c --environment BUILD:production && npm run compile-uninstaller", "compile-tests": "tsc -p . --outDir out", diff --git a/src/activator.mts b/src/activator.mts index 0101c23..c2f4d49 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -488,8 +488,7 @@ export default class Activator { } commandExecuting = true; - this.terminal?.clean(true); - this.terminal?.write("\r\n"); + this.terminal?.cleanAndStore(); this.ui?.userOperationStarted(); }, (data: Buffer) => { @@ -506,9 +505,7 @@ export default class Activator { this.logger.warn("Failed to execute script on Pico."); } commandExecuting = false; - this.terminal?.melt(); - this.terminal?.write("\r\n"); - this.terminal?.prompt(); + this.terminal?.restore(); } ); context.subscriptions.push(disposable); @@ -559,8 +556,7 @@ export default class Activator { // tells the terminal that it should // emit input events to relay user input commandExecuting = true; - this.terminal?.clean(true); - this.terminal?.write("\r\n"); + this.terminal?.cleanAndStore(); this.ui?.userOperationStarted(); }, (data: Buffer) => { @@ -574,9 +570,7 @@ export default class Activator { } this.ui?.userOperationStopped(); commandExecuting = false; - this.terminal?.melt(); - this.terminal?.write("\r\n"); - this.terminal?.prompt(); + this.terminal?.restore(); } ); context.subscriptions.push(disposable); @@ -616,8 +610,7 @@ export default class Activator { } commandExecuting = true; - this.terminal?.clean(true); - this.terminal?.write("\r\n"); + this.terminal?.cleanAndStore(); this.ui?.userOperationStarted(); }, (data: Buffer) => { @@ -634,8 +627,7 @@ export default class Activator { // const result = data as PyOutCommandResult; // TODO: reflect result.result in status bar } - this.terminal?.melt(); - this.terminal?.prompt(); + this.terminal?.restore(); } } ); @@ -1339,9 +1331,6 @@ export default class Activator { } await focusTerminal(this.terminalOptions); - // performing hard reset in orange - this.terminal?.write("\x1b[33mPerforming hard reset...\x1b[0m\r\n"); - const result = await PicoMpyCom.getInstance().hardReset( (open: boolean) => { if (!open) { @@ -1349,14 +1338,17 @@ export default class Activator { } commandExecuting = true; - this.terminal?.clean(true); - this.terminal?.write("\r\n"); + this.terminal?.cleanAndStore(); this.ui?.userOperationStarted(); + + // inform user about ongoing operation + this.terminal?.write("\x1b[33mPerforming hard reset...\x1b[0m\r\n"); }, (data: Buffer) => { this.terminal?.write(data.toString("utf-8")); } ); + this.terminal?.restore(); commandExecuting = false; this.ui?.userOperationStopped(); if (result.type === OperationResultType.commandResult) { diff --git a/src/terminal.mts b/src/terminal.mts index 2b56757..23b52f2 100644 --- a/src/terminal.mts +++ b/src/terminal.mts @@ -9,6 +9,14 @@ const DEL = (count: number): string => `\x1b[${count}D\x1b[1P`; // Ctrl+D; Ctrl+E const IGNORED_CHARS = ["\x04", "\x05"]; +interface TerminalState { + buffer: string; + multilineMode: boolean; + indentation: number; + xCursor: number; + waitingForPrompt: boolean; +} + /** * A pseudo terminal (aka vREPL) so the serial connection can be used by * other parts of the extension while the user isn't executing a command in the REPL. @@ -21,13 +29,16 @@ export class Terminal implements Pseudoterminal { private submitEmitter = new EventEmitter(); private tabCompEmitter = new EventEmitter(); private isOpen = false; - private buffer = ""; - private multilineMode = false; - private indentation = 0; - private waitingForPrompt = false; + private state: TerminalState = { + buffer: "", + multilineMode: false, + indentation: 0, + xCursor: 0, + waitingForPrompt: false, + }; + private backupState?: TerminalState; private history: History = new History(); private controlSequence = false; - private xCursor = 0; private isFrozen = false; private awaitingCloseOp = false; @@ -87,13 +98,13 @@ export class Terminal implements Pseudoterminal { } public clean(waitingForPrompt?: boolean): void { - this.waitingForPrompt = waitingForPrompt ?? this.waitingForPrompt; + this.state.waitingForPrompt = + waitingForPrompt ?? this.state.waitingForPrompt; - // TODO: maybe restore current state - this.buffer = ""; - this.multilineMode = false; - this.indentation = 0; - this.xCursor = 0; + this.state.buffer = ""; + this.state.multilineMode = false; + this.state.indentation = 0; + this.state.xCursor = 0; } public melt(): void { @@ -101,13 +112,14 @@ export class Terminal implements Pseudoterminal { } private getRelativeCursor(): number { - let relativeCursor = this.xCursor; - if (this.multilineMode) { - const currentLineLength = this.buffer.split("\n").pop()?.length; + let relativeCursor = this.state.xCursor; + if (this.state.multilineMode) { + const currentLineLength = this.state.buffer.split("\n").pop()?.length; if (currentLineLength === undefined) { return -1; } - relativeCursor = this.xCursor + (this.buffer.length - currentLineLength); + relativeCursor = + this.state.xCursor + (this.state.buffer.length - currentLineLength); } return relativeCursor; @@ -127,42 +139,43 @@ export class Terminal implements Pseudoterminal { const historyItem = this.history.arrowUp(); // delete until last save positon this.writeEmitter.fire("\x1b[u\x1b[0J"); - this.buffer = historyItem; - this.xCursor = this.buffer.length; - this.writeEmitter.fire(this.buffer); + this.state.buffer = historyItem; + this.state.xCursor = this.state.buffer.length; + this.writeEmitter.fire(this.state.buffer); } else if (data === "\x1b[B") { // arrow down const historyItem = this.history.arrowDown(); // delete until last save positon this.writeEmitter.fire("\x1b[u\x1b[0J"); - this.buffer = historyItem; - this.xCursor = this.buffer.length; - this.writeEmitter.fire(this.buffer); + this.state.buffer = historyItem; + this.state.xCursor = this.state.buffer.length; + this.writeEmitter.fire(this.state.buffer); } else if (data === "\x1b[C") { // arrow right - if (this.xCursor < this.buffer.length) { - this.xCursor++; + if (this.state.xCursor < this.state.buffer.length) { + this.state.xCursor++; this.writeEmitter.fire("\x1b[1C"); } } else if (data === "\x1b[D") { // arrow left if ( - this.xCursor > 0 && - (!this.multilineMode || this.indentation < this.xCursor) + this.state.xCursor > 0 && + (!this.state.multilineMode || + this.state.indentation < this.state.xCursor) ) { - this.xCursor--; + this.state.xCursor--; this.writeEmitter.fire("\x1b[1D"); } } else if ( data === "\x1b[3~" && - this.xCursor < this.buffer.split("\n")[-1].length + this.state.xCursor < this.state.buffer.split("\n")[-1].length ) { // delete this.writeEmitter.fire("\x1b[0K"); // delete the character (if any) right of the cursor, index of which will be xCursor - this.buffer = - this.buffer.slice(0, this.xCursor) + - this.buffer.slice(this.xCursor + 1); + this.state.buffer = + this.state.buffer.slice(0, this.state.xCursor) + + this.state.buffer.slice(this.state.xCursor + 1); } break; @@ -170,30 +183,30 @@ export class Terminal implements Pseudoterminal { if (char === "\r") { // don't allow multiline imput while we're waiting for a prompt - if (!this.waitingForPrompt) { + if (!this.state.waitingForPrompt) { this.checkMultilineMode(); } if ( - this.multilineMode && - this.buffer.split("\n").pop()?.trim() === "" + this.state.multilineMode && + this.state.buffer.split("\n").pop()?.trim() === "" ) { - this.multilineMode = false; + this.state.multilineMode = false; this.processMultilineInput(); - this.buffer = ""; - this.xCursor = 0; + this.state.buffer = ""; + this.state.xCursor = 0; } else { - if (!this.multilineMode) { - if (this.buffer === "") { + if (!this.state.multilineMode) { + if (this.state.buffer === "") { this.writeEmitter.fire("\r\n"); this.prompt(); } else { - this.processInput(this.buffer); + this.processInput(this.state.buffer); } - this.buffer = ""; - this.xCursor = 0; + this.state.buffer = ""; + this.state.xCursor = 0; } else { - this.buffer += "\n"; + this.state.buffer += "\n"; this.writeEmitter.fire("\r\n"); this.handleIndentation(); } @@ -206,13 +219,13 @@ export class Terminal implements Pseudoterminal { this.controlSequence = true; } else if (char === "\x03") { // Ctrl+C - if (!this.waitingForPrompt) { + if (!this.state.waitingForPrompt) { return; } this.submitEmitter.fire(char); } else if (char === "\t") { - if (this.multilineMode) { + if (this.state.multilineMode) { // Tab is treated as 4 spaces in multiline mode and not // for autocompletion like in normal mode this.handleInput(" "); @@ -233,51 +246,51 @@ export class Terminal implements Pseudoterminal { return; } - // this.buffer += char; for xCursor - this.buffer = - this.buffer.slice(0, relativeCursor) + + // this.state.buffer += char; for xCursor + this.state.buffer = + this.state.buffer.slice(0, relativeCursor) + char + - this.buffer.slice(relativeCursor); + this.state.buffer.slice(relativeCursor); // if xCursor is not at the end of the row - if (relativeCursor < this.buffer.length) { + if (relativeCursor < this.state.buffer.length) { // shift the rest of the row to the right, to don't overwrite it this.writeEmitter.fire("\x1b[1@"); } this.writeEmitter.fire(char); - this.xCursor++; + this.state.xCursor++; } } } private handleIndentation(): void { - const lastLine = this.buffer.split("\n").slice(-2)[0]; + const lastLine = this.state.buffer.split("\n").slice(-2)[0]; if (lastLine.trim().endsWith(":")) { - this.indentation += 4; - this.xCursor = this.indentation; + this.state.indentation += 4; + this.state.xCursor = this.state.indentation; } - const indentStr = " ".repeat(this.indentation); + const indentStr = " ".repeat(this.state.indentation); this.writeEmitter.fire(indentStr); - this.buffer += indentStr; + this.state.buffer += indentStr; } private handleBackspace(): void { - const currentLine = this.buffer.split("\n").pop(); + const currentLine = this.state.buffer.split("\n").pop(); if (currentLine === undefined) { return; } if ( - this.multilineMode && - this.indentation > 0 && - currentLine?.length === this.indentation && + this.state.multilineMode && + this.state.indentation > 0 && + currentLine?.length === this.state.indentation && currentLine.trim() === "" ) { - this.indentation -= 4; - this.xCursor -= 4; + this.state.indentation -= 4; + this.state.xCursor -= 4; // Remove the last 4 characters from the buffer - this.buffer = this.buffer.slice(0, -4); + this.state.buffer = this.state.buffer.slice(0, -4); this.writeEmitter.fire(DEL(4)); } else if (currentLine.length > 0) { const relativeCursor = this.getRelativeCursor(); @@ -286,22 +299,22 @@ export class Terminal implements Pseudoterminal { } // Remove the last character from the buffer at relativeCursor-1 - this.buffer = - this.buffer.slice(0, relativeCursor - 1) + - this.buffer.slice(relativeCursor); - this.xCursor--; + this.state.buffer = + this.state.buffer.slice(0, relativeCursor - 1) + + this.state.buffer.slice(relativeCursor); + this.state.xCursor--; this.writeEmitter.fire(DEL(1)); } } private handleTab(): void { - if (this.buffer === "") { + if (this.state.buffer === "") { return; } // move cursor into next line this.writeEmitter.fire("\r\n"); - this.tabCompEmitter.fire(this.buffer); + this.tabCompEmitter.fire(this.state.buffer); } private checkMultilineMode(): void { @@ -318,9 +331,9 @@ export class Terminal implements Pseudoterminal { "except", "finally", ]; - const lastLine = this.buffer.split("\n").pop() ?? ""; - if (!this.multilineMode) { - this.multilineMode = multilineKeywords.some(keyword => + const lastLine = this.state.buffer.split("\n").pop() ?? ""; + if (!this.state.multilineMode) { + this.state.multilineMode = multilineKeywords.some(keyword => lastLine.trim().startsWith(keyword) ); } @@ -348,14 +361,14 @@ export class Terminal implements Pseudoterminal { return; } else if (input === ".ls") { this.writeEmitter.fire("\r\n"); - this.waitingForPrompt = true; + this.state.waitingForPrompt = true; this.history.add(input); this.submitEmitter.fire("import uos; uos.listdir()\n"); return; } else if (input === ".rtc") { this.writeEmitter.fire("\r\n"); - this.waitingForPrompt = true; + this.state.waitingForPrompt = true; this.history.add(input); PicoMpyCom.getInstance() .getRtcTime() @@ -412,25 +425,25 @@ export class Terminal implements Pseudoterminal { return; } - if (this.waitingForPrompt) { + if (this.state.waitingForPrompt) { // delete input as input(...) in repl echos input back this.writeEmitter.fire(DEL(input.length)); } else { this.writeEmitter.fire("\r\n"); } - this.waitingForPrompt = true; + this.state.waitingForPrompt = true; this.history.add(input); this.submitEmitter.fire(input + "\n"); } private processMultilineInput(): void { //this.writeEmitter.fire("\nMultiline input submitted\r\n"); - this.indentation = 0; + this.state.indentation = 0; this.writeEmitter.fire("\r\n"); - this.waitingForPrompt = true; - this.history.add(this.buffer); - this.submitEmitter.fire(this.buffer); + this.state.waitingForPrompt = true; + this.history.add(this.state.buffer); + this.submitEmitter.fire(this.state.buffer); } public write(data: string): void { @@ -438,7 +451,7 @@ export class Terminal implements Pseudoterminal { } public prompt(withoutPrint = false): void { - this.waitingForPrompt = false; + this.state.waitingForPrompt = false; if (!withoutPrint) { this.writeEmitter.fire(PROMPT); } @@ -449,4 +462,50 @@ export class Terminal implements Pseudoterminal { public getIsOpen(): boolean { return this.isOpen; } + + private clearState(): void { + this.state = { + buffer: "", + multilineMode: false, + indentation: 0, + xCursor: 0, + waitingForPrompt: false, + }; + } + + /** + * Clean the terminal and store the current state (not submitted input). + * + * Can be used in combination with restore to keep the terminal state + * during an external operation. + */ + public cleanAndStore(): void { + this.backupState = { ...this.state }; + // delete until last save positon + this.writeEmitter.fire("\x1b[u\x1b[0J"); + this.clean(true); + this.writeEmitter.fire("\r\n"); + } + + /** + * Restore the terminal state after an external operation. + * + * (does trigger prompt and newline for you) + */ + public restore(): void { + // check if last content is prompt + this.writeEmitter.fire("\r\n"); + this.prompt(); + if (this.backupState !== undefined) { + this.clearState(); + + // write buffer + /*for (const char of this.backupState.buffer) { + this.handleInput(char); + }*/ + this.state = { ...this.backupState }; + this.writeEmitter.fire(this.state.buffer); + this.backupState = undefined; + } + } } From a7bbf6a07c8697999f9983f059b1d74a0cd62e7a Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:19:59 +0100 Subject: [PATCH 04/13] Fix eslint cfg Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- eslint.config.mjs | 3 +++ src/activitybar/deviceWifiTree.mts | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 3239efa..4b63115 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -39,6 +39,9 @@ export default tseslint.config( "@typescript-eslint/naming-convention": "warn", "@typescript-eslint/no-unused-vars": "warn", "@typescript-eslint/no-explicit-any": "warn", + "@typescript-eslint/no-unused-expressions": ["error", { "allowShortCircuit": true }], + "@typescript-eslint/dot-notation": ["error", { "allowKeywords": true }], + "@typescript-eslint/no-empty-function": ["warn", { "allow": ["arrowFunctions"] }], "@typescript-eslint/array-type": ["error", { default: "array-simple" }], "@typescript-eslint/consistent-type-imports": ["error", { prefer: "type-imports" }], "@typescript-eslint/explicit-function-return-type": ["error", { allowExpressions: true }], diff --git a/src/activitybar/deviceWifiTree.mts b/src/activitybar/deviceWifiTree.mts index 28b3741..8d53c78 100644 --- a/src/activitybar/deviceWifiTree.mts +++ b/src/activitybar/deviceWifiTree.mts @@ -251,7 +251,7 @@ export default class DeviceWifiProvider implements TreeDataProvider { } // eslint-disable-next-line @typescript-eslint/no-unused-vars - public async getChildren(element?: Wifi | undefined): Promise { + public async getChildren(element?: Wifi): Promise { const networks = await PicoMpyCom.getInstance().runCommand( DETECT_WIFIS_SCRIPT ); From f8e37a489312907e6e7a69e4bee4a18c69e2da14 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:23:21 +0100 Subject: [PATCH 05/13] Switch to release build for Pico 2 Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- src/downloadFirmware.mts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/downloadFirmware.mts b/src/downloadFirmware.mts index 7817fc6..5abbca6 100644 --- a/src/downloadFirmware.mts +++ b/src/downloadFirmware.mts @@ -77,11 +77,7 @@ export async function downloadFirmware( firmwareType: SupportedFirmwareTypes ): Promise { const url = firmwareTypeToDownloadURL(firmwareType); - const uf2Url = await extractUf2Url( - url, - // TODO: remove after stable builds for Pico2 are available - firmwareType === SupportedFirmwareTypes.pico2 - ); + const uf2Url = await extractUf2Url(url, false); if (!uf2Url) { console.error("No UF2 URL found."); From 0f00e4ef29a105e61de7ad7620abd84b51914fe9 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:51:42 +0100 Subject: [PATCH 06/13] Implemented boot.py warnings Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- src/activator.mts | 47 +++++++++++++++++++++++++++++++++++++++++++++-- src/terminal.mts | 6 +++--- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/activator.mts b/src/activator.mts index c2f4d49..5d3ef78 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -1264,7 +1264,7 @@ export default class Activator { // [Command] Hard reset pico disposable = vscode.commands.registerCommand( commandPrefix + "reset.hard", - () => { + async () => { // TODO: maybe instead just run the command and if it retuns a type none // response show warning message as otherwise a second warning for this // case would be required to be implemented @@ -1275,6 +1275,11 @@ export default class Activator { return; } + + if (await this.bootPyWarning()) { + return; + } + // performing hard reset in orange void vscode.window.withProgress( { @@ -1318,7 +1323,7 @@ export default class Activator { // [Command] Hard reset pico (interactive) disposable = vscode.commands.registerCommand( commandPrefix + "reset.hard.listen", - async () => { + async (terminalTriggered = false) => { // TODO: maybe instead just run the command and if it retuns a type none // response show warning message as otherwise a second warning for this // case would be required to be implemented @@ -1330,6 +1335,15 @@ export default class Activator { return; } + if (await this.bootPyWarning()) { + if (terminalTriggered) { + this.terminal?.clean(true); + this.terminal?.prompt(); + } + + return; + } + await focusTerminal(this.terminalOptions); const result = await PicoMpyCom.getInstance().hardReset( (open: boolean) => { @@ -1980,4 +1994,33 @@ export default class Activator { ` ); } + + private async bootPyWarning(): Promise { + const bootPyResult = await PicoMpyCom.getInstance().getItemStat("/boot.py"); + + if ( + bootPyResult.type === OperationResultType.getItemStat && + bootPyResult.stat !== null + ) { + // warn that boot.py could prevent device from entering REPL or delay the amount we have to wait before we can reconnect + const result = await vscode.window.showWarningMessage( + "A boot.py script is present on the Pico. " + + "If it contains an infinite loop or long running code, " + + "the Pico may not enter the REPL or take longer to do so. " + + "Do you want to continue?", + { modal: true }, + "Yes" + ); + + return result !== "Yes"; + } else { + void vscode.window.showErrorMessage( + "Failed to retrieve details about the boot.py file." + ); + } + + // continue as we don't know if there is a boot.py file + // or the user wants to continue even if there is one + return false; + } } diff --git a/src/terminal.mts b/src/terminal.mts index 23b52f2..57051bf 100644 --- a/src/terminal.mts +++ b/src/terminal.mts @@ -394,16 +394,16 @@ export class Terminal implements Pseudoterminal { return; } else if (input === ".sr") { - commands.executeCommand(commandPrefix + "reset.soft.listen"); + void commands.executeCommand(commandPrefix + "reset.soft.listen"); return; } else if (input === ".hr") { - commands.executeCommand(commandPrefix + "reset.hard.listen"); + void commands.executeCommand(commandPrefix + "reset.hard.listen", true); this.writeEmitter.fire("\r\n"); return; } else if (input === ".gc") { - commands.executeCommand(commandPrefix + "garbageCollect"); + void commands.executeCommand(commandPrefix + "garbageCollect"); this.writeEmitter.fire("\r\n"); this.prompt(); From 975a7ebeeda5b0b5c6f708e8d254a3cdc39840ea Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 21:01:26 +0100 Subject: [PATCH 07/13] Rename configure project command Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 7d85aea..34bd854 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,8 @@ }, { "command": "micropico.initialise", - "title": "Configure MicroPico Project", + "title": "Setup MicroPico project", + "enablement": "(resourceScheme != pico && isFileSystemResource) || inQuickOpen", "category": "MicroPico" }, { From fcfb23388adee956bb5af739d61ac8127f55cb1f Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:08:01 +0100 Subject: [PATCH 08/13] Reload settings before project uploads Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- src/activator.mts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/activator.mts b/src/activator.mts index 5d3ef78..04b6e97 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -651,6 +651,7 @@ export default class Activator { return; } + this.settings.reload(); const syncDir = await this.settings.requestSyncFolder("Upload"); From e6ef377c2f074a9ce2799ce21a065c399f3df42f Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 22:44:29 +0100 Subject: [PATCH 09/13] Upgrade to pico-mpy-com v1.0.21 Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index edbf38f..5ef1819 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "linux" ], "dependencies": { - "@paulober/pico-mpy-com": "^1.0.20", + "@paulober/pico-mpy-com": "^1.0.21", "@vscode/python-extension": "^1.0.5", "axios": "^1.7.7", "fs-extra": "^11.2.0", @@ -394,9 +394,9 @@ } }, "node_modules/@paulober/pico-mpy-com": { - "version": "1.0.20", - "resolved": "https://npm.pkg.github.com/download/@paulober/pico-mpy-com/1.0.20/0a10e7e473b664b1ec0c455a3d35612452ed89a8", - "integrity": "sha512-6+VcEJr8V7XRr7M1cuZNjDUDuOZcWj9ixyj5d4k0sT6lDaxwgH23Tjv8Asx4mvZqsBzw3wxpDf6q5lYYW0lDcA==", + "version": "1.0.21", + "resolved": "https://npm.pkg.github.com/download/@paulober/pico-mpy-com/1.0.21/cf1bcbe60352120467eed01216c94272ad2c6892", + "integrity": "sha512-G7iS1MGyAVFYd/owvwXPssq8gH6jyC8e8kRqLEfzmBt6uPY0Jh5rIN9OS9LgCJuySnK9kilsjGoQPLOhT3rr7Q==", "cpu": [ "x64", "arm64" diff --git a/package.json b/package.json index 34bd854..abee6d7 100644 --- a/package.json +++ b/package.json @@ -659,7 +659,7 @@ "typescript-eslint": "^8.14.0" }, "dependencies": { - "@paulober/pico-mpy-com": "^1.0.20", + "@paulober/pico-mpy-com": "^1.0.21", "@vscode/python-extension": "^1.0.5", "axios": "^1.7.7", "fs-extra": "^11.2.0", From 9bc9b2e3883965f7c2b8ac648805c9b72e8fbb7d Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:09:22 +0100 Subject: [PATCH 10/13] Fix #257, Switch to machine-overridable scope for all settings Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package.json | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index abee6d7..0d03188 100644 --- a/package.json +++ b/package.json @@ -330,7 +330,7 @@ "properties": { "micropico.autoConnect": { "type": "boolean", - "scope": "resource", + "scope": "machine-overridable", "default": true, "title": "Autoconnect on USB", "description": "Ignores any 'device address' setting and automatically connects to the top item in the serialport list.", @@ -338,7 +338,7 @@ }, "micropico.manualComDevice": { "type": "string", - "scope": "resource", + "scope": "machine-overridable", "default": "", "title": "Manual COM device", "description": "If autoConnect is set to false MicroPico will automatically connect to the serial port specified here.", @@ -346,7 +346,7 @@ }, "micropico.syncFolder": { "type": "string", - "scope": "resource", + "scope": "machine-overridable", "default": "", "title": "Sync Folder", "description": "This folder will be uploaded to the pyboard when using the sync button. Leave empty to sync the complete project. (only allows folders within the project). Use a path relative to the project you opened in vscode, without leading or trailing slash", @@ -354,7 +354,7 @@ }, "micropico.additionalSyncFolders": { "type": "array", - "scope": "resource", + "scope": "machine-overridable", "items": { "type": "string", "uniqueItems": true @@ -366,15 +366,15 @@ }, "micropico.syncAllFileTypes": { "type": "boolean", + "scope": "machine-overridable", "default": false, - "scope": "resource", "title": "Upload all file types", "description": "If enabled, all files will be uploaded no matter the file type. The list of file types below will be ignored", "order": 6 }, "micropico.syncFileTypes": { "type": "array", - "scope": "resource", + "scope": "machine-overridable", "items": { "type": "string", "uniqueItems": true @@ -396,7 +396,7 @@ }, "micropico.pyIgnore": { "title": "Pyignore list", - "scope": "resource", + "scope": "machine-overridable", "markdownDescription": "Comma separated list of files and folders to ignore when uploading relative to syncFolder (no wildcard or regular expressions supported except `**/` to exclude an item by its name in every sub folder). Use `:file/to/exclude.py` to create sync folder exclusive exclusion rules (all other rules will always be applied relative to the selected sync folder). Replace `additionalSyncFolder` with a value from your `micropico.additionalSyncFolders` setting or the value from `micropico.syncFolder`.", "type": "array", "items": { @@ -427,8 +427,8 @@ }, "micropico.statusbarButtons": { "type": "array", + "scope": "machine-overridable", "title": "Statusbar buttons", - "scope": "resource", "description": "Select which buttons to show in the statusbar", "items": { "type": "string", @@ -468,30 +468,31 @@ }, "micropico.softResetAfterUpload": { "type": "boolean", + "scope": "machine-overridable", "default": false, - "scope": "resource", "title": "Soft-reset after upload", "description": "Soft-resets your board after any upload action which also reruns main.py and boot.py. Usefull when working with main.py and boot.py.", "order": 12 }, "micropico.executeOnConnect": { "type": "string", + "scope": "machine-overridable", "default": "", - "scope": "resource", "title": "Script to execute on connect", "description": "Path to a MicroPython script on the Pico to execute on connect. Leave empty to disable.", "order": 13 }, "micropico.importOnConnect": { "type": "string", + "scope": "machine-overridable", "default": "", - "scope": "resource", "title": "MicroPython module to import on connect", "description": "A MicroPython module to import in vREPL on connect. Leave empty to disable.", "order": 14 }, "micropico.noSoftResetOnRun": { "type": "boolean", + "scope": "machine-overridable", "default": false, "title": "Disable the soft-resets before and after executing a file.", "description": "Soft-resets are used to clean REPL state so changes in classes and other structs are reflected correctly.", From 6ff83aa7383f2a0ac8f3206613d2df2dd69a72ef Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Mon, 18 Nov 2024 00:07:12 +0100 Subject: [PATCH 11/13] Detect if firmware is in subdirectory by locating .micropico file as default root Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package.json | 2 +- src/activator.mts | 1 + src/osHelper.mts | 24 +++++++++++++++++++++++- src/settings.mts | 48 +++++++++++++++++++++++++++++++++++++++-------- src/stubs.mts | 1 - 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 0d03188..b0b4e89 100644 --- a/package.json +++ b/package.json @@ -347,7 +347,7 @@ "micropico.syncFolder": { "type": "string", "scope": "machine-overridable", - "default": "", + "default": null, "title": "Sync Folder", "description": "This folder will be uploaded to the pyboard when using the sync button. Leave empty to sync the complete project. (only allows folders within the project). Use a path relative to the project you opened in vscode, without leading or trailing slash", "order": 4 diff --git a/src/activator.mts b/src/activator.mts index 04b6e97..aafc938 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -972,6 +972,7 @@ export default class Activator { return; } + this.settings.reload(); const syncDir = await this.settings.requestSyncFolder("Download"); diff --git a/src/osHelper.mts b/src/osHelper.mts index 9871072..86fc93d 100644 --- a/src/osHelper.mts +++ b/src/osHelper.mts @@ -1,5 +1,6 @@ -import { lstat } from "fs"; +import { lstat, readdirSync } from "fs"; import { readFile, stat, writeFile } from "fs/promises"; +import { basename, join } from "path"; import { rimrafSync } from "rimraf"; export async function pathExists(path: string): Promise { @@ -61,3 +62,24 @@ export function removeJunction(junctionPath: string): Promise { }); }); } + +/** + * Searches for a file in a directory and its subdirectories. + * + * @param directory The directory to search in. + * @param fileName The name of the file to search for. + * @returns The path to the file if found, otherwise undefined. + */ +export function searchFile( + directory: string, + fileName: string +): string | undefined { + const contents = readdirSync(directory, { + encoding: "utf8", + recursive: true, + }); + + const file = contents.find(c => basename(c) === fileName); + + return file ? join(directory, file) : undefined; +} diff --git a/src/settings.mts b/src/settings.mts index c7552ef..6776568 100644 --- a/src/settings.mts +++ b/src/settings.mts @@ -1,8 +1,9 @@ import type { Memento, Uri, WorkspaceConfiguration } from "vscode"; import { window, workspace as vsWorkspace } from "vscode"; import { extName, getProjectPath, settingsStubsBasePath } from "./api.mjs"; -import { join, relative } from "path"; +import { dirname, join, relative } from "path"; import { PicoMpyCom } from "@paulober/pico-mpy-com"; +import { searchFile } from "./osHelper.mjs"; export enum SettingsKey { autoConnect = "autoConnect", @@ -75,6 +76,10 @@ export default class Settings { return this.config.update(key, value, true); } + public updateWorkspaceFolder(key: string, value: T): Thenable { + return this.config.update(key, value, null); + } + public updatePython(key: string, value: T): Thenable { return this.pythonConfig.update(key, value, null); } @@ -126,22 +131,22 @@ export default class Settings { * Returns the absolute path to the sync folder. If the sync folder is undefined, * the project path is returned. * - * @returns the absolute path to the sync folder + * @returns The absolute path to the sync folder and if the setting is undefined */ - public getSyncFolderAbsPath(): string | undefined { + public getSyncFolderAbsPath(): [string | undefined, boolean] { const syncDir = this.getString(SettingsKey.syncFolder); const projectDir = getProjectPath(); - if (syncDir === undefined) { - return projectDir; + if (syncDir === undefined || syncDir.length === 0) { + return [projectDir, true]; } if (projectDir === undefined) { // How can this ever happen??! - return undefined; + return [undefined, false]; } - return join(projectDir, syncDir); + return [join(projectDir, syncDir), false]; } /** @@ -158,7 +163,7 @@ export default class Settings { public async requestSyncFolder( actionTitle: string ): Promise<[string, string] | undefined> { - const syncFolder = this.getSyncFolderAbsPath(); + let [syncFolder, syncSettingNotSet] = this.getSyncFolderAbsPath(); const projectDir = getProjectPath(); if (projectDir === undefined) { @@ -166,6 +171,33 @@ export default class Settings { return; } + // sync folder setting not set + if (syncSettingNotSet) { + const activationFile = searchFile(projectDir, ".micropico"); + const actParent = activationFile ? dirname(activationFile) : undefined; + + // check if activation file is not in project root + if (activationFile && actParent && actParent !== projectDir) { + syncFolder = actParent; + + // update transparent to the user + await this.updateWorkspaceFolder( + SettingsKey.syncFolder, + relative(projectDir, actParent) + ); + + void window.showWarningMessage( + `Sync folder has been set to \`${relative( + projectDir, + actParent + )}\` ` + + "because the `.micropico` file was found in a subdirectory " + + "and no sync folder was set. To disable this behavior, " + + "set a sync folder in the settings to `.` for the project root." + ); + } + } + let additionalSyncFolders = this.getArray( SettingsKey.additionalSyncFolders )?.map(sf => join(projectDir, sf)); diff --git a/src/stubs.mts b/src/stubs.mts index 007de17..939351a 100644 --- a/src/stubs.mts +++ b/src/stubs.mts @@ -191,7 +191,6 @@ export default class Stubs { }; if (!justUpdate) { - defaultSettings["micropico.syncFolder"] = ""; defaultSettings["micropico.openOnStart"] = true; } From 5043cd0c653e1b567f59af56037a14859717bde5 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Mon, 18 Nov 2024 00:46:44 +0100 Subject: [PATCH 12/13] Added redirectOutput experimental command Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- package.json | 13 +++++++++ src/activator.mts | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/package.json b/package.json index b0b4e89..3ae64b9 100644 --- a/package.json +++ b/package.json @@ -233,6 +233,12 @@ "command": "micropico.flashPico", "title": "Flash Pico in BOOTSEL mode", "category": "MicroPico" + }, + { + "command": "micropico.redirectOutput", + "title": "MicroPython output redirection settings (experimental)", + "category": "MicroPico", + "enablement": "micropico.isConnected" } ], "menus": { @@ -323,6 +329,13 @@ "when": "view == micropico-device-wifi", "group": "navigation@0" } + ], + "terminal/context": [ + { + "command": "micropico.redirectOutput", + "group": "MicroPico", + "when": "micropico.isConnected" + } ] }, "configuration": { diff --git a/src/activator.mts b/src/activator.mts index aafc938..0748ad4 100644 --- a/src/activator.mts +++ b/src/activator.mts @@ -38,6 +38,7 @@ import { PythonExtension, } from "@vscode/python-extension"; import { flashPicoInteractively } from "./flash.mjs"; +import { appendFileSync } from "fs"; /*const pkg: {} | undefined = vscode.extensions.getExtension("paulober.pico-w-go") ?.packageJSON as object;*/ @@ -58,6 +59,9 @@ export default class Activator { private autoConnectTimer?: NodeJS.Timeout; private comDevice?: string; private noCheckForUSBMSDs = false; + // TODO: currently only used as file path - replace with proper type + // to support different target if needed + private outputRedirectionTarget?: string; constructor() { this.logger = new Logger("Activator"); @@ -207,6 +211,7 @@ export default class Activator { }, (data: Buffer) => { if (data.length > 0) { + this.redirectOutput(data); this.terminal?.write(data.toString("utf-8")); } }, @@ -493,6 +498,7 @@ export default class Activator { }, (data: Buffer) => { if (data.length > 0) { + this.redirectOutput(data); this.terminal?.write(data.toString("utf-8")); } } @@ -561,6 +567,7 @@ export default class Activator { }, (data: Buffer) => { if (data.length > 0) { + this.redirectOutput(data); this.terminal?.write(data.toString("utf-8")); } } @@ -615,6 +622,7 @@ export default class Activator { }, (data: Buffer) => { if (data.length > 0) { + this.redirectOutput(data); this.terminal?.write(data.toString("utf-8")); } }, @@ -1361,6 +1369,7 @@ export default class Activator { this.terminal?.write("\x1b[33mPerforming hard reset...\x1b[0m\r\n"); }, (data: Buffer) => { + this.redirectOutput(data); this.terminal?.write(data.toString("utf-8")); } ); @@ -1401,6 +1410,7 @@ export default class Activator { } }, (data: Buffer) => { + this.redirectOutput(data); this.terminal?.write(data.toString("utf-8")); } ); @@ -1642,6 +1652,50 @@ export default class Activator { ); context.subscriptions.push(disposable); + // TODO: add context key to show command in context menu only if vREPL is focused + disposable = vscode.commands.registerCommand( + commandPrefix + "redirectOutput", + async () => { + const location = await vscode.window.showQuickPick( + ["$(x) Disable", "$(info) Status", "$(arrow-right) File"], + { + canPickMany: false, + placeHolder: "Select the output location or manage settings", + title: "Output redirection for this session", + ignoreFocusOut: false, + } + ); + + switch (location) { + case "$(x) Disable": + this.outputRedirectionTarget = undefined; + break; + case "$(info) Status": + // show status if disabled to redirected into a file with path + void vscode.window.showInformationMessage( + this.outputRedirectionTarget + ? `Output is redirected to: ${this.outputRedirectionTarget}` + : "Output redirection is disabled" + ); + break; + case "$(arrow-right) File": + const file = await vscode.window.showSaveDialog({ + filters: { + "Text files": ["txt"], + "Log files": ["log"], + "All files": ["*"], + }, + saveLabel: "Save output to file", + }); + + if (file) { + this.outputRedirectionTarget = file.fsPath; + } + break; + } + } + ); + const packagesWebviewProvider = new PackagesWebviewProvider( context.extensionUri ); @@ -2025,4 +2079,21 @@ export default class Activator { // or the user wants to continue even if there is one return false; } + + // TODO: maybe use a stream instead of spaming syscalls + private redirectOutput(data: Buffer): void { + if (this.outputRedirectionTarget === undefined) { + return; + } + + try { + appendFileSync(this.outputRedirectionTarget, data); + } catch (error) { + this.logger.error( + `Failed to redirect output to file: ${ + error instanceof Error ? error.message : error + }` + ); + } + } } From 6b38b4eb80c2e6e51c31c08365a4db67d7028de9 Mon Sep 17 00:00:00 2001 From: paulober <44974737+paulober@users.noreply.github.com> Date: Mon, 18 Nov 2024 00:57:58 +0100 Subject: [PATCH 13/13] v4.1.0 Signed-off-by: paulober <44974737+paulober@users.noreply.github.com> --- CHANGELOG.md | 19 +++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 846b6cc..1bdb59a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,25 @@ All notable changes to the "MicroPico" extension will be documented in this file --- +## [4.1.0] - 2024-11-18 + +### Added + +- Restore behavior for terminal content if an external action is triggered and takes over the terminal (like run file) +- Boot.py warnings when performing hard resets +- `micropico.redirectOutput` experimental command to redirect output of operations like running files into other target than the terminal (like a file) + +### Changed + +- Updated dependencies +- Upgraded to `pyboard-serial-com` `v1.0.21` (Fixes #254) +- Better Python utilization in stub switcher +- Switch to release build for Pico 2 auto installs +- Configure project command has been renamed to `Setup MicroPico project` +- Reload settings before uploading and downloading projects to detect settings changes +- SyncFolder auto-detection based on `.micropico` file location if not set +- All settings are now scoped `machine-overridable` + ## [4.0.6] - 2024-09-16 ### Added diff --git a/package-lock.json b/package-lock.json index 5ef1819..01b7dff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pico-w-go", - "version": "4.0.6", + "version": "4.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pico-w-go", - "version": "4.0.6", + "version": "4.1.0", "cpu": [ "x64", "arm64", diff --git a/package.json b/package.json index 3ae64b9..78788bf 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "pico-w-go", "displayName": "MicroPico", "description": "Auto-completion, remote workspace and a REPL console integration for the Raspberry Pi Pico boards running MicroPython firmware.", - "version": "4.0.6", + "version": "4.1.0", "publisher": "paulober", "license": "MPL-2.0", "homepage": "https://github.com/paulober/MicroPico/blob/main/README.md",