From 07538cf0059bba7e0b76252310f6512f763eca41 Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 13:46:21 -0400 Subject: [PATCH 1/8] Upgrade eslint to flat config file --- .eslintignore | 9 - .eslintrc.json | 48 ---- eslint.config.mjs | 70 ++++++ package-lock.json | 544 ++++++++++++++++++++-------------------------- package.json | 10 +- 5 files changed, 310 insertions(+), 371 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.json create mode 100644 eslint.config.mjs diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 1fa76a19a3..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,9 +0,0 @@ -.vscode-test -.wdio-vscode-service -**/*.d.ts -**/*/__mocks__ -node_modules -dist -out -src/test/fixtures -src/test/integration/*/workspace/** diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index a40db1f102..0000000000 --- a/.eslintrc.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "root": true, - "extends": ["eslint:recommended"], - "env": { - "browser": true, - "es2021": true - }, - "parserOptions": { - "ecmaFeatures": { - "jsx": false - }, - "ecmaVersion": 12, - "sourceType": "module" - }, - "rules": { - "curly": "warn", - "eqeqeq": "warn", - "no-throw-literal": "warn", - "semi": "off" - }, - "overrides": [ - { - "files": ["**/*.ts"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 6, - "sourceType": "module" - }, - "plugins": ["@typescript-eslint", "prettier"], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended", - "prettier" - ], - "rules": { - "@typescript-eslint/no-explicit-any": ["warn", { "ignoreRestArgs": true }], - "@typescript-eslint/naming-convention": "off", - "@typescript-eslint/semi": "warn", - "curly": "warn", - "eqeqeq": "warn", - "no-throw-literal": "warn", - "semi": "off" - } - } - ] -} diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000000..7588d8d660 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,70 @@ +import pluginJs from '@eslint/js'; +import prettierConfig from 'eslint-config-prettier'; +import globals from 'globals'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import tseslint from 'typescript-eslint'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export default [ + pluginJs.configs.recommended, + ...tseslint.configs.strictTypeChecked, + ...tseslint.configs.stylisticTypeChecked, + ...tseslint.configs.recommendedTypeChecked, + prettierConfig, + { + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: __dirname, + }, + globals: { ...globals.browser, ...globals.node }, + }, + }, + { + files: ['**/*.ts'], + rules: { + curly: 'warn', + eqeqeq: 'warn', + 'no-throw-literal': 'warn', + semi: 'warn', + '@typescript-eslint/no-explicit-any': ['warn', { ignoreRestArgs: true }], + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/no-unsafe-assignment': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + '@typescript-eslint/no-unsafe-member-access': 'warn', + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowNumber: true, + }, + ], + '@typescript-eslint/class-literal-property-style': ['error', 'getters'], + }, + }, + { + files: ['src/api/**/*.ts'], + rules: { + // We do not want to change HCP API contracts + '@typescript-eslint/consistent-indexed-object-style': 'off', + }, + }, + { + files: ['**/*.{js,mjs,cjs}'], + ...tseslint.configs.disableTypeChecked, + }, + { + ignores: [ + '.vscode-test', + '.wdio-vscode-service', + 'dist', + 'out', + 'src/test', + '**/node_modules/**', + '**/out/**', + '**/dist/**', + ], + }, +]; diff --git a/package-lock.json b/package-lock.json index 3dea56bd06..63b833dd26 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ }, "devDependencies": { "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@eslint/js": "^9.11.0", "@hashicorp/js-releases": "^1.7.1", "@playwright/browser-chromium": "^1.39.0", "@types/chai": "^4.3.5", @@ -30,8 +31,6 @@ "@types/semver": "^7.5.8", "@types/vscode": "~1.86", "@types/which": "^3.0.0", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", "@vscode/test-cli": "^0.0.9", "@vscode/test-electron": "^2.3.9", "@vscode/test-web": "^0.0.56", @@ -43,9 +42,9 @@ "assert": "^2.0.0", "chai": "^4.3.7", "esbuild": "^0.23.0", - "eslint": "^8.57.0", + "eslint": "^9.11.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.9.0", "mocha": "^10.2.0", "msw": "^2.0.11", "npm-run-all": "^4.1.5", @@ -53,6 +52,7 @@ "process": "^0.11.10", "ts-node": "^10.9.2", "typescript": "^5.1.3", + "typescript-eslint": "^8.6.0", "wdio-vscode-service": "^6.0.3", "wdio-wait-for": "^3.0.11" }, @@ -553,25 +553,51 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "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.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "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==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -579,19 +605,52 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.11.0.tgz", + "integrity": "sha512-LPkkenkDqyzTFauZLLAPhIb48fj6drrfMvRGSL9tS3AcZBSVTllemLSNyCvHNNL2t797S/6DJNSIwRwXgMO/eQ==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@fastify/accept-negotiator": { @@ -731,21 +790,6 @@ "yauzl": "^2.10.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -759,12 +803,18 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@inquirer/confirm": { "version": "3.1.4", @@ -1274,18 +1324,6 @@ "node": ">=14" } }, - "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/@playwright/browser-chromium": { "version": "1.45.3", "resolved": "https://registry.npmjs.org/@playwright/browser-chromium/-/browser-chromium-1.45.3.tgz", @@ -1603,31 +1641,31 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.17.0.tgz", - "integrity": "sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.6.0.tgz", + "integrity": "sha512-UOaz/wFowmoh2G6Mr9gw60B1mm0MzUtm6Ic8G2yM1Le6gyj5Loi/N+O5mocugRGY+8OeeKmkMmbxNqUCq3B4Sg==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/type-utils": "7.17.0", - "@typescript-eslint/utils": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/type-utils": "8.6.0", + "@typescript-eslint/utils": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1636,26 +1674,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.17.0.tgz", - "integrity": "sha512-puiYfGeg5Ydop8eusb/Hy1k7QmOU6X3nvsqCgzrB2K4qMavK//21+PzNE8qeECgNOIoertJPUC1SpegHDI515A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.6.0.tgz", + "integrity": "sha512-eQcbCuA2Vmw45iGfcyG4y6rS7BhWfz9MQuk409WD47qMM+bKCGQWXxvoOs1DUp+T7UBMTtRTVT+kXr7Sh4O9Ow==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -1664,16 +1702,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.17.0.tgz", - "integrity": "sha512-0P2jTTqyxWp9HiKLu/Vemr2Rg1Xb5B7uHItdVZ6iAenXmPo4SZ86yOPCJwMqpCyaMiEHTNqizHfsbmCFT1x9SA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.6.0.tgz", + "integrity": "sha512-ZuoutoS5y9UOxKvpc/GkvF4cuEmpokda4wRg64JEia27wX+PysIE9q+lzDtlHHgblwUWwo5/Qn+/WyTUvDwBHw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0" + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1681,26 +1719,23 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.17.0.tgz", - "integrity": "sha512-XD3aaBt+orgkM/7Cei0XNEm1vwUxQ958AOLALzPlbPqb8C1G8PZK85tND7Jpe69Wualri81PLU+Zc48GVKIMMA==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.6.0.tgz", + "integrity": "sha512-dtePl4gsuenXVwC7dVNlb4mGDcKjDT/Ropsk4za/ouMBPplCLyznIaR+W65mvCvsyS97dymoBRrioEXI7k0XIg==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.17.0", - "@typescript-eslint/utils": "7.17.0", + "@typescript-eslint/typescript-estree": "8.6.0", + "@typescript-eslint/utils": "8.6.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -1708,12 +1743,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.17.0.tgz", - "integrity": "sha512-a29Ir0EbyKTKHnZWbNsrc/gqfIBqYPwj3F2M+jWE/9bqfEHg0AMtXzkbUkOG6QgEScxh2+Pz9OXe11jHDnHR7A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.6.0.tgz", + "integrity": "sha512-rojqFZGd4MQxw33SrOy09qIDS8WEldM8JWtKQLAjf/X5mGSeEFh5ixQlxssMNyPslVIk9yzWqXCsV2eFhYrYUw==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1721,22 +1756,22 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.17.0.tgz", - "integrity": "sha512-72I3TGq93t2GoSBWI093wmKo0n6/b7O4j9o8U+f65TVD0FS6bI2180X5eGEr8MA8PhKMvYe9myZJquUT2JkCZw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.6.0.tgz", + "integrity": "sha512-MOVAzsKJIPIlLK239l5s06YXjNqpKTVhBVDnqUumQJja5+Y94V3+4VUFRA0G60y2jNnTVwRCkhyGQpavfsbq/g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/visitor-keys": "7.17.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/visitor-keys": "8.6.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1773,49 +1808,55 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.17.0.tgz", - "integrity": "sha512-r+JFlm5NdB+JXc7aWWZ3fKSm1gn0pkswEwIYsrGPdsT2GjsRATAKXiNtp3vgAAO1xZhX8alIOEQnNMl3kbTgJw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.6.0.tgz", + "integrity": "sha512-eNp9cWnYf36NaOVjkEUznf6fEgVy1TWpE0o52e4wtojjBx7D1UV2WAWGzR+8Y5lVFtpMLPwNbC67T83DWSph4A==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.17.0", - "@typescript-eslint/types": "7.17.0", - "@typescript-eslint/typescript-estree": "7.17.0" + "@typescript-eslint/scope-manager": "8.6.0", + "@typescript-eslint/types": "8.6.0", + "@typescript-eslint/typescript-estree": "8.6.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.17.0.tgz", - "integrity": "sha512-RVGC9UhPOCsfCdI9pU++K4nD7to+jTcMIbXTSOcrLqUEW6gF2pU1UUbYJKc9cvcRSK1UDeMJ7pdMxf4bhMpV/A==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.6.0.tgz", + "integrity": "sha512-wapVFfZg9H0qOYh4grNVQiMklJGluQrOUiOhYRrQWhx7BY/+I1IYb8BczWNbbUpO+pqy0rDciv3lQH5E1bCLrg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.17.0", + "@typescript-eslint/types": "8.6.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/@vitest/pretty-format": { "version": "2.0.5", @@ -2701,9 +2742,9 @@ } }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3111,15 +3152,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", @@ -4980,30 +5012,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -5549,43 +5557,39 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.11.0.tgz", + "integrity": "sha512-yVS6XODx+tMFMDFcG4+Hlh+qG7RM6cCJXtQhCKLSsr3XkLvWggHjCqjfh0XsPPnt1c56oaT6PMgW9XWQQjdHXA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.11.0", + "@eslint/plugin-kit": "^0.2.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.0.2", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", @@ -5597,10 +5601,18 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -5615,59 +5627,29 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.2.tgz", + "integrity": "sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "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==", "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -5756,17 +5738,17 @@ } }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.1.0.tgz", + "integrity": "sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==", "dev": true, "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.12.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -6018,12 +6000,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -6270,15 +6246,15 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-type": { @@ -6395,17 +6371,16 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { @@ -6944,15 +6919,12 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6974,26 +6946,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/globule": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", @@ -7464,9 +7416,9 @@ ] }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -10944,15 +10896,6 @@ "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", "dev": true }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", @@ -11245,18 +11188,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/pretty-format": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", @@ -12972,22 +12903,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/synckit": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz", - "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==", - "dev": true, - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -13322,18 +13237,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -13444,6 +13347,29 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.6.0.tgz", + "integrity": "sha512-eEhhlxCEpCd4helh3AO1hk0UP2MvbRi9CtIAJTVPQjuSXOOO2jsEacNi4UdcJzZJbeuVg1gMhtZ8UYb+NFYPrA==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.6.0", + "@typescript-eslint/parser": "8.6.0", + "@typescript-eslint/utils": "8.6.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", diff --git a/package.json b/package.json index 43b37e57fe..ee9a8bde7f 100644 --- a/package.json +++ b/package.json @@ -948,7 +948,7 @@ "pretest": "npm run compile:tests && npm run compile && npm run lint", "test": "vscode-test", "wdio": "npm run compile && wdio run ./src/test/e2e/wdio.conf.ts", - "lint": "eslint src --ext ts", + "lint": "eslint", "prettier": "prettier \"**/*.+(js|json|ts)\"", "format": "npm run prettier -- --write", "check-types": "tsc --noEmit", @@ -968,6 +968,7 @@ }, "devDependencies": { "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@eslint/js": "^9.11.0", "@hashicorp/js-releases": "^1.7.1", "@playwright/browser-chromium": "^1.39.0", "@types/chai": "^4.3.5", @@ -977,8 +978,6 @@ "@types/semver": "^7.5.8", "@types/vscode": "~1.86", "@types/which": "^3.0.0", - "@typescript-eslint/eslint-plugin": "^7.17.0", - "@typescript-eslint/parser": "^7.17.0", "@vscode/test-cli": "^0.0.9", "@vscode/test-electron": "^2.3.9", "@vscode/test-web": "^0.0.56", @@ -990,9 +989,9 @@ "assert": "^2.0.0", "chai": "^4.3.7", "esbuild": "^0.23.0", - "eslint": "^8.57.0", + "eslint": "^9.11.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.9.0", "mocha": "^10.2.0", "msw": "^2.0.11", "npm-run-all": "^4.1.5", @@ -1000,6 +999,7 @@ "process": "^0.11.10", "ts-node": "^10.9.2", "typescript": "^5.1.3", + "typescript-eslint": "^8.6.0", "wdio-vscode-service": "^6.0.3", "wdio-wait-for": "^3.0.11" } From 23f5d245be559be64f3a6c9e8cb5e390a6bc806b Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 14:39:45 -0400 Subject: [PATCH 2/8] Configure prettier to work with eslint --- .prettierignore | 3 +++ package.json | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.prettierignore b/.prettierignore index 918df5e377..c4bf9c29c4 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,7 @@ .vscode-test .vscode-test-web .wdio-vscode-service +.changes language-configuration.json node_modules dist @@ -10,3 +11,5 @@ snippets src/test/fixtures src/test/integration/*/workspace/** syntaxes +docs +*.md diff --git a/package.json b/package.json index ee9a8bde7f..34fcf8a041 100644 --- a/package.json +++ b/package.json @@ -949,10 +949,9 @@ "test": "vscode-test", "wdio": "npm run compile && wdio run ./src/test/e2e/wdio.conf.ts", "lint": "eslint", - "prettier": "prettier \"**/*.+(js|json|ts)\"", - "format": "npm run prettier -- --write", + "format": "prettier --write .", "check-types": "tsc --noEmit", - "check-format": "npm run prettier -- --check", + "check-format": "prettier --check .", "changelog:build": "changie batch auto && changie merge && npm i --package-lock-only" }, "dependencies": { From 230f48596ade50fa9b274b2921a2976093e7aad5 Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 14:44:28 -0400 Subject: [PATCH 3/8] Run prettier format --- .changie.yaml | 20 ++++----- .github/ISSUE_TEMPLATE/bug_report.yml | 4 +- .github/ISSUE_TEMPLATE/documentation.yml | 4 +- .github/ISSUE_TEMPLATE/feature_request.yml | 4 +- .github/ISSUE_TEMPLATE/performance.yml | 4 +- .github/dependabot.yml | 26 ++++++------ .github/release.yml | 2 +- .github/workflows/add-copyright-headers.yml | 2 +- .github/workflows/stale.yml | 46 ++++++++++----------- .vscode-test.mjs | 13 +++--- 10 files changed, 62 insertions(+), 63 deletions(-) diff --git a/.changie.yaml b/.changie.yaml index 2b8e4dad14..c0a5dd613e 100644 --- a/.changie.yaml +++ b/.changie.yaml @@ -24,16 +24,16 @@ custom: type: int minInt: 1 kinds: -- label: ENHANCEMENTS - auto: minor -- label: BUG FIXES - auto: patch -- label: INTERNAL - auto: patch -- label: NOTES - auto: patch -- label: BREAKING CHANGES - auto: minor + - label: ENHANCEMENTS + auto: minor + - label: BUG FIXES + auto: patch + - label: INTERNAL + auto: patch + - label: NOTES + auto: patch + - label: BREAKING CHANGES + auto: minor newlines: afterKind: 1 beforeKind: 1 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 84957ae4f7..9e6f7e8405 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,5 +1,5 @@ -name: "Bug report" -description: "Let us know about an unexpected error, a crash, or an incorrect behavior." +name: 'Bug report' +description: 'Let us know about an unexpected error, a crash, or an incorrect behavior.' labels: [bug] assignees: [] body: diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml index 2db2945fa8..6d1701b1fc 100644 --- a/.github/ISSUE_TEMPLATE/documentation.yml +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -1,5 +1,5 @@ -name: "Documentation issue or request" -description: "Report an issue with our docs or Marketplace listing, or suggest additions and improvements to our documentation" +name: 'Documentation issue or request' +description: 'Report an issue with our docs or Marketplace listing, or suggest additions and improvements to our documentation' labels: [documentation] assignees: [] body: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index f528799a8b..da15327768 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,5 +1,5 @@ -name: "Feature request" -description: "Suggest a new feature or other enhancement." +name: 'Feature request' +description: 'Suggest a new feature or other enhancement.' labels: [enhancement] assignees: [] body: diff --git a/.github/ISSUE_TEMPLATE/performance.yml b/.github/ISSUE_TEMPLATE/performance.yml index d363fb854e..f3cc789b85 100644 --- a/.github/ISSUE_TEMPLATE/performance.yml +++ b/.github/ISSUE_TEMPLATE/performance.yml @@ -1,5 +1,5 @@ -name: "Performance issue report" -description: "Let us know about issues with performance, such as slow speed or abnormally high CPU or memory usage." +name: 'Performance issue report' +description: 'Let us know about issues with performance, such as slow speed or abnormally high CPU or memory usage.' labels: [performance] assignees: [] body: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7cbc57df0e..a4cc8e4e43 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,22 +1,20 @@ version: 2 updates: - - package-ecosystem: "npm" + - package-ecosystem: 'npm' versioning-strategy: lockfile-only - directory: "/" + directory: '/' schedule: - interval: "daily" - labels: ["dependencies"] + interval: 'daily' + labels: ['dependencies'] ignore: - - dependency-name: "@types/*" - update-types: - ["version-update:semver-minor", "version-update:semver-patch"] - - dependency-name: "@typescript-eslint/*" - update-types: - ["version-update:semver-minor", "version-update:semver-patch"] + - dependency-name: '@types/*' + update-types: ['version-update:semver-minor', 'version-update:semver-patch'] + - dependency-name: '@typescript-eslint/*' + update-types: ['version-update:semver-minor', 'version-update:semver-patch'] # Dependabot only updates hashicorp GHAs, external GHAs are managed by internal tooling (tsccr) - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: 'github-actions' + directory: '/' schedule: - interval: "daily" + interval: 'daily' allow: - - dependency-name: "hashicorp/*" + - dependency-name: 'hashicorp/*' diff --git a/.github/release.yml b/.github/release.yml index d237c2e5a5..4e744a9765 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -20,7 +20,7 @@ changelog: labels: - dependencies - ci - - "*" + - '*' exclude: labels: - duplicate diff --git a/.github/workflows/add-copyright-headers.yml b/.github/workflows/add-copyright-headers.yml index d8e762f722..61dd376e82 100644 --- a/.github/workflows/add-copyright-headers.yml +++ b/.github/workflows/add-copyright-headers.yml @@ -1,4 +1,4 @@ -name: "Add Copyright Headers" +name: 'Add Copyright Headers' on: pull_request_target: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 6b4052b606..49e9a1ea18 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,4 +1,4 @@ -name: "Stale issues and pull requests" +name: 'Stale issues and pull requests' permissions: issues: write @@ -6,38 +6,38 @@ permissions: on: schedule: - - cron: "10 3 * * *" + - cron: '10 3 * * *' jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 - with: - only-labels: 'waiting-response' + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 + with: + only-labels: 'waiting-response' - days-before-stale: 30 - stale-issue-label: 'stale' - stale-issue-message: | - Marking this issue as stale due to inactivity over the last 30 days. This helps our maintainers find and focus on the active issues. If this issue receives no comments in the next **30 days** it will automatically be closed. Maintainers can also remove the stale label. + days-before-stale: 30 + stale-issue-label: 'stale' + stale-issue-message: | + Marking this issue as stale due to inactivity over the last 30 days. This helps our maintainers find and focus on the active issues. If this issue receives no comments in the next **30 days** it will automatically be closed. Maintainers can also remove the stale label. - Thank you for understanding. - stale-pr-label: 'stale' - stale-pr-message: | - Marking this pull request as stale due to inactivity over the last 30 days. This helps our maintainers find and focus on the active pull requests. If this pull request receives no comments in the next **30 days** it will automatically be closed. Maintainers can also remove the stale label. + Thank you for understanding. + stale-pr-label: 'stale' + stale-pr-message: | + Marking this pull request as stale due to inactivity over the last 30 days. This helps our maintainers find and focus on the active pull requests. If this pull request receives no comments in the next **30 days** it will automatically be closed. Maintainers can also remove the stale label. - Thank you for understanding. + Thank you for understanding. - days-before-close: 30 - close-issue-message: | - Closing this issue due to its staleness. + days-before-close: 30 + close-issue-message: | + Closing this issue due to its staleness. - If the issue was automatically closed and you feel it should be reopened, we encourage creating a new one linking back to this one for added context. + If the issue was automatically closed and you feel it should be reopened, we encourage creating a new one linking back to this one for added context. - Thank you! - close-pr-message: | - Closing this pull request due to its staleness. + Thank you! + close-pr-message: | + Closing this pull request due to its staleness. - If the pull request was automatically closed and you feel it should be reopened, we encourage creating a new one linking back to this one for added context. + If the pull request was automatically closed and you feel it should be reopened, we encourage creating a new one linking back to this one for added context. - Thank you! + Thank you! diff --git a/.vscode-test.mjs b/.vscode-test.mjs index af135e8705..e477712057 100644 --- a/.vscode-test.mjs +++ b/.vscode-test.mjs @@ -11,14 +11,15 @@ import path from 'path'; const BASE_SRC_PATH = './src/test/integration'; const BASE_OUT_PATH = './out/test/integration'; -const testSuiteFolderNames = fs.readdirSync(BASE_SRC_PATH, { withFileTypes: true }) - .filter(entry => entry.isDirectory()) // only directories ... - .filter(entry => fs.existsSync(path.join(BASE_SRC_PATH, entry.name, "workspace"))) // ... that contain a workspace folder are valid - .map(entry => entry.name); +const testSuiteFolderNames = fs + .readdirSync(BASE_SRC_PATH, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) // only directories ... + .filter((entry) => fs.existsSync(path.join(BASE_SRC_PATH, entry.name, 'workspace'))) // ... that contain a workspace folder are valid + .map((entry) => entry.name); -const configs = testSuiteFolderNames.map(folderName => ({ +const configs = testSuiteFolderNames.map((folderName) => ({ version: process.env['VSCODE_VERSION'] ?? 'stable', - workspaceFolder: process.env['VSCODE_WORKSPACE_FOLDER'] ?? path.join(BASE_SRC_PATH, folderName, "workspace"), + workspaceFolder: process.env['VSCODE_WORKSPACE_FOLDER'] ?? path.join(BASE_SRC_PATH, folderName, 'workspace'), launchArgs: ['--disable-extensions', '--disable-workspace-trust'], files: `${BASE_OUT_PATH}/${folderName}/*.test.js`, mocha: { From 89768186cfa276d5711893ef58886063e6c05618 Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 15:52:26 -0400 Subject: [PATCH 4/8] extension eslint fixes --- esbuild.js | 2 +- eslint.config.mjs | 14 ++++---- src/api/terraform/terraform.ts | 17 +++++---- src/api/terraformCloud/filter.ts | 2 +- src/api/terraformCloud/index.ts | 7 +++- src/api/terraformCloud/instance.ts | 11 ------ src/api/terraformCloud/run.ts | 2 +- src/commands/generateBugReport.ts | 12 ++++--- src/commands/terraform.ts | 9 +++-- src/commands/terraformls.ts | 10 +++--- src/extension.ts | 15 ++++---- src/features/languageStatus.ts | 10 ++---- src/features/moduleCalls.ts | 26 +++++++------- src/features/moduleProviders.ts | 23 ++++++------ src/features/semanticTokens.ts | 2 +- src/features/showReferences.ts | 20 +++++------ src/features/telemetry.ts | 23 ++++++------ src/features/terraformCloud.ts | 20 +++++------ src/features/terraformVersion.ts | 16 ++++----- src/providers/terraform/moduleCalls.ts | 39 +++++++++++---------- src/providers/terraform/moduleProviders.ts | 30 ++++++++-------- src/providers/tfc/applyProvider.ts | 20 +++++------ src/providers/tfc/authenticationProvider.ts | 26 +++++++------- src/providers/tfc/logHelpers.ts | 11 +++--- src/providers/tfc/organizationPicker.ts | 4 +-- src/providers/tfc/planProvider.ts | 22 ++++++------ src/providers/tfc/runProvider.ts | 35 ++++++++---------- src/providers/tfc/uiHelpers.ts | 6 ++-- src/providers/tfc/workspaceFilters.ts | 4 +-- src/providers/tfc/workspaceProvider.ts | 28 +++++++-------- src/utils/clientHelpers.ts | 1 + src/utils/serverPath.ts | 4 ++- 32 files changed, 227 insertions(+), 244 deletions(-) diff --git a/esbuild.js b/esbuild.js index 2a8cf88607..36f0972cb2 100644 --- a/esbuild.js +++ b/esbuild.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -/* eslint-disable no-undef */ + const esbuild = require('esbuild'); const glob = require('glob'); const path = require('path'); diff --git a/eslint.config.mjs b/eslint.config.mjs index 7588d8d660..56db239a1b 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -23,6 +23,13 @@ export default [ globals: { ...globals.browser, ...globals.node }, }, }, + { + files: ['src/api/**/*.ts'], + rules: { + // We do not want to change HCP API contracts + '@typescript-eslint/consistent-indexed-object-style': 'off', + }, + }, { files: ['**/*.ts'], rules: { @@ -44,13 +51,6 @@ export default [ '@typescript-eslint/class-literal-property-style': ['error', 'getters'], }, }, - { - files: ['src/api/**/*.ts'], - rules: { - // We do not want to change HCP API contracts - '@typescript-eslint/consistent-indexed-object-style': 'off', - }, - }, { files: ['**/*.{js,mjs,cjs}'], ...tseslint.configs.disableTypeChecked, diff --git a/src/api/terraform/terraform.ts b/src/api/terraform/terraform.ts index 5e87dce0e2..a5e2c04ba2 100644 --- a/src/api/terraform/terraform.ts +++ b/src/api/terraform/terraform.ts @@ -10,7 +10,7 @@ import { Utils } from 'vscode-uri'; import { getActiveTextEditor } from './../../utils/vscode'; import { clientSupportsCommand } from './../../utils/clientHelpers'; -/* eslint-disable @typescript-eslint/naming-convention */ + export interface ModuleCaller { uri: string; } @@ -53,7 +53,6 @@ export interface TerraformInfoResponse { required_version?: string; discovered_version?: string; } -/* eslint-enable @typescript-eslint/naming-convention */ export async function terraformVersion( moduleUri: string, @@ -121,7 +120,9 @@ export async function initAskUserCommand(client: LanguageClient, reporter: Telem const moduleUri = selected[0]; const command = `terraform-ls.terraform.init`; - return execWorkspaceLSCommand(command, moduleUri.toString(), client, reporter); + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + await execWorkspaceLSCommand(command, moduleUri.toString(), client, reporter); + return; } catch (error) { if (error instanceof Error) { vscode.window.showErrorMessage(error.message); @@ -187,7 +188,7 @@ async function terraformCommand( } const terminal = - vscode.window.terminals.find((t) => t.name === terminalName) || + vscode.window.terminals.find((t) => t.name === terminalName) ?? vscode.window.createTerminal({ name: `Terraform ${selectedModule}`, cwd: moduleURI }); terminal.sendText(terraformCommand); terminal.show(); @@ -198,7 +199,8 @@ async function terraformCommand( const fullCommand = `terraform-ls.terraform.${command}`; - return execWorkspaceLSCommand(fullCommand, selectedModule, client, reporter); + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + await execWorkspaceLSCommand(fullCommand, selectedModule, client, reporter); } async function execWorkspaceLSCommand( @@ -226,15 +228,12 @@ async function execWorkspaceLSCommand( arguments: [`uri=${moduleUri}`], }; + // eslint-disable-next-line @typescript-eslint/no-invalid-void-type return client.sendRequest(ExecuteCommandRequest.type, params); } async function getSelectedModule(moduleUri: vscode.Uri, moduleCallers: ModuleCaller[]): Promise { let selectedModule: string; - if (moduleCallers === undefined) { - return moduleUri.toString(); - } - if (moduleCallers.length > 1) { const selected = await vscode.window.showQuickPick( moduleCallers.map((m) => m.uri), diff --git a/src/api/terraformCloud/filter.ts b/src/api/terraformCloud/filter.ts index 1d110d1efd..787e1bf981 100644 --- a/src/api/terraformCloud/filter.ts +++ b/src/api/terraformCloud/filter.ts @@ -22,7 +22,7 @@ export const workspaceIncludeParams = makeParameters([ description: 'Includes related resources for workspaces when specified', schema: z .array(z.enum(['current_run'])) - .transform((x) => x?.join(',')) + .transform((x) => x.join(',')) .optional(), }, ]); diff --git a/src/api/terraformCloud/index.ts b/src/api/terraformCloud/index.ts index 3c98cee368..94229fc73c 100644 --- a/src/api/terraformCloud/index.ts +++ b/src/api/terraformCloud/index.ts @@ -24,17 +24,20 @@ export let TerraformCloudHost = 'app.terraform.io'; export let TerraformCloudAPIUrl = `https://${TerraformCloudHost}/api/v2`; export let TerraformCloudWebUrl = `https://${TerraformCloudHost}/app`; +// eslint-disable-next-line @typescript-eslint/require-await const jsonHeader = pluginHeader('Content-Type', async () => 'application/vnd.api+json'); // TODO: Consider passing it as a dependency instead of global access to make testing easier const extVersion = vscode.extensions.getExtension('hashicorp.terraform')?.packageJSON.version; const userAgentHeader = pluginHeader( 'User-Agent', + // eslint-disable-next-line @typescript-eslint/require-await async () => `VSCode/${vscode.version} hashicorp.terraform/${extVersion}`, ); function pluginLogger(): ZodiosPlugin { return { + // eslint-disable-next-line @typescript-eslint/require-await response: async (_api, _config, response) => { console.log(response); return response; @@ -44,6 +47,7 @@ function pluginLogger(): ZodiosPlugin { function responseHeaderLogger(): ZodiosPlugin { return { + // eslint-disable-next-line @typescript-eslint/require-await response: async (api, config, response) => { console.log('Response appname:', response.headers['tfp-appname']); console.log('Response api-version:', response.headers['tfp-api-version']); @@ -89,7 +93,8 @@ export const tokenPluginId = apiClient.use( const session = await vscode.authentication.getSession(TerraformCloudAuthenticationProvider.providerID, [], { createIfNone: true, }); - return session ? session.accessToken : undefined; + // return session ? session.accessToken : undefined; + return session.accessToken; }, }), ); diff --git a/src/api/terraformCloud/instance.ts b/src/api/terraformCloud/instance.ts index 377c2fd912..93b1459b4c 100644 --- a/src/api/terraformCloud/instance.ts +++ b/src/api/terraformCloud/instance.ts @@ -7,17 +7,6 @@ import { makeApi } from '@zodios/core'; import { z } from 'zod'; import { errors } from './errors'; -const hcpInstance = z.object({ - appName: z.string().nullish(), - apiVersion: z.string().nullish(), -}); -export type HCPInstance = z.infer; - -const details = z.object({ - data: hcpInstance, -}); -export type HCPInstanceDetails = z.infer; - export const pingEndpoints = makeApi([ { method: 'get', diff --git a/src/api/terraformCloud/run.ts b/src/api/terraformCloud/run.ts index b8c258261f..1acb92847a 100644 --- a/src/api/terraformCloud/run.ts +++ b/src/api/terraformCloud/run.ts @@ -121,7 +121,7 @@ const includeParams = makeParameters([ 'configuration_version.ingress_attributes', ]), ) - .transform((x) => x?.join(',')) + .transform((x) => x.join(',')) .optional(), }, ]); diff --git a/src/commands/generateBugReport.ts b/src/commands/generateBugReport.ts index 90b87d9650..9166cbf997 100644 --- a/src/commands/generateBugReport.ts +++ b/src/commands/generateBugReport.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -import child_process = require('child_process'); +import * as child_process from 'child_process'; import * as os from 'os'; import * as vscode from 'vscode'; @@ -30,7 +30,7 @@ export class GenerateBugReportCommand implements vscode.Disposable { }); const extensions = this.getExtensions(); - const body = await this.generateBody(extensions, problemText); + const body = this.generateBody(extensions, problemText); const encodedBody = encodeURIComponent(body); const fullUrl = `https://github.com/hashicorp/vscode-terraform/issues/new?body=${encodedBody}`; vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(fullUrl)); @@ -42,7 +42,7 @@ export class GenerateBugReportCommand implements vscode.Disposable { // throw new Error('Method not implemented.'); } - async generateBody(extensions: VSCodeExtension[], problemText?: string): Promise { + generateBody(extensions: VSCodeExtension[], problemText?: string): string { if (!problemText) { problemText = `Steps To Reproduce ===== @@ -97,7 +97,7 @@ Environment Information Terraform Information ----- -${this.generateRuntimeMarkdown(await this.getRuntimeInfo())} +${this.generateRuntimeMarkdown(this.getRuntimeInfo())} Visual Studio Code ----- @@ -154,9 +154,11 @@ Outdated:\t${info.outdated} const extensions = vscode.extensions.all .filter((element) => element.packageJSON.isBuiltin === false) .sort((leftside, rightside): number => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call if (leftside.packageJSON.name.toLowerCase() < rightside.packageJSON.name.toLowerCase()) { return -1; } + // eslint-disable-next-line @typescript-eslint/no-unsafe-call if (leftside.packageJSON.name.toLowerCase() > rightside.packageJSON.name.toLowerCase()) { return 1; } @@ -172,7 +174,7 @@ Outdated:\t${info.outdated} return extensions; } - async getRuntimeInfo(): Promise { + getRuntimeInfo(): TerraformInfo { const terraformExe = 'terraform'; const spawn = child_process.spawnSync; diff --git a/src/commands/terraform.ts b/src/commands/terraform.ts index 142d5f2004..9b3c244ee0 100644 --- a/src/commands/terraform.ts +++ b/src/commands/terraform.ts @@ -9,13 +9,12 @@ import { LanguageClient } from 'vscode-languageclient/node'; import * as terraform from '../api/terraform/terraform'; export class TerraformCommands implements vscode.Disposable { - private commands: vscode.Disposable[]; - constructor( private client: LanguageClient, private reporter: TelemetryReporter, + private context: vscode.ExtensionContext, ) { - this.commands = [ + this.context.subscriptions.push( vscode.commands.registerCommand('terraform.init', async () => { await terraform.initAskUserCommand(this.client, this.reporter); }), @@ -31,10 +30,10 @@ export class TerraformCommands implements vscode.Disposable { vscode.commands.registerCommand('terraform.validate', async () => { await terraform.command('validate', this.client, this.reporter); }), - ]; + ); } dispose() { - this.commands.forEach((c) => c.dispose()); + // } } diff --git a/src/commands/terraformls.ts b/src/commands/terraformls.ts index 3aa33c7ec6..8000aae627 100644 --- a/src/commands/terraformls.ts +++ b/src/commands/terraformls.ts @@ -7,10 +7,8 @@ import * as vscode from 'vscode'; import { config, getScope } from '../utils/vscode'; export class TerraformLSCommands implements vscode.Disposable { - private commands: vscode.Disposable[]; - - constructor() { - this.commands = [ + constructor(private context: vscode.ExtensionContext) { + this.context.subscriptions.push( vscode.workspace.onDidChangeConfiguration(async (event: vscode.ConfigurationChangeEvent) => { if (event.affectsConfiguration('terraform') || event.affectsConfiguration('terraform-ls')) { const reloadMsg = 'Reload VSCode window to apply language server changes'; @@ -52,10 +50,10 @@ export class TerraformLSCommands implements vscode.Disposable { }); } }), - ]; + ); } dispose() { - this.commands.forEach((c) => c.dispose()); + // } } diff --git a/src/extension.ts b/src/extension.ts index 89b40e13df..75710005d2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -51,7 +51,7 @@ const tfcOutputChannel = vscode.window.createOutputChannel('HCP Terraform'); let reporter: TelemetryReporter; let client: LanguageClient; -let initializationError: ResponseError | undefined = undefined; +let initializationError: ResponseError | Error | undefined; let crashCount = 0; export async function activate(context: vscode.ExtensionContext): Promise { @@ -60,7 +60,7 @@ export async function activate(context: vscode.ExtensionContext): Promise context.subscriptions.push(reporter); // always register commands needed to control terraform-ls - context.subscriptions.push(new TerraformLSCommands()); + context.subscriptions.push(new TerraformLSCommands(context)); context.subscriptions.push(new TerraformCloudFeature(context, reporter, tfcOutputChannel)); @@ -94,8 +94,8 @@ export async function activate(context: vscode.ExtensionContext): Promise outputChannel: outputChannel, revealOutputChannelOn: RevealOutputChannelOn.Never, initializationOptions: initializationOptions, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - initializationFailedHandler: (error: ResponseError | Error | any) => { + + initializationFailedHandler: (error: ResponseError | Error) => { initializationError = error; reporter.sendTelemetryException(error); @@ -145,10 +145,9 @@ export async function activate(context: vscode.ExtensionContext): Promise return false; }, errorHandler: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars error: (error: Error, message: Message, count: number) => { return { - message: `Terraform LS connection error: (${count ?? 0})\n${error?.message}\n${message?.jsonrpc}`, + message: `Terraform LS connection error: (${count})\n${error.message}\n${message.jsonrpc}`, action: ErrorAction.Shutdown, }; }, @@ -217,7 +216,7 @@ export async function activate(context: vscode.ExtensionContext): Promise ]); // these need the LS to function, so are only registered if enabled - context.subscriptions.push(new GenerateBugReportCommand(context), new TerraformCommands(client, reporter)); + context.subscriptions.push(new GenerateBugReportCommand(context), new TerraformCommands(client, reporter, context)); try { await client.start(); @@ -228,7 +227,7 @@ export async function activate(context: vscode.ExtensionContext): Promise export async function deactivate(): Promise { try { - await client?.stop(); + await client.stop(); } catch (error) { if (error instanceof Error) { outputChannel.appendLine(error.message); diff --git a/src/features/languageStatus.ts b/src/features/languageStatus.ts index 7b8d9b830c..61fd6867c2 100644 --- a/src/features/languageStatus.ts +++ b/src/features/languageStatus.ts @@ -11,8 +11,6 @@ import { ExperimentalClientCapabilities } from './types'; import * as lsStatus from '../status/language'; export class LanguageStatusFeature implements StaticFeature { - private disposables: vscode.Disposable[] = []; - constructor( private client: BaseLanguageClient, private reporter: TelemetryReporter, @@ -29,8 +27,8 @@ export class LanguageStatusFeature implements StaticFeature { } public fillClientCapabilities(capabilities: ClientCapabilities & ExperimentalClientCapabilities): void { - if (!capabilities['experimental']) { - capabilities['experimental'] = {}; + if (!capabilities.experimental) { + capabilities.experimental = {}; } } @@ -45,8 +43,4 @@ export class LanguageStatusFeature implements StaticFeature { lsStatus.setVersion(initializeResult.serverInfo?.version ?? ''); } - - public dispose(): void { - this.disposables.forEach((d: vscode.Disposable) => d.dispose()); - } } diff --git a/src/features/moduleCalls.ts b/src/features/moduleCalls.ts index 67e5ee8e43..0870056c55 100644 --- a/src/features/moduleCalls.ts +++ b/src/features/moduleCalls.ts @@ -17,9 +17,8 @@ import { ExperimentalClientCapabilities } from './types'; const CLIENT_MODULE_CALLS_CMD_ID = 'client.refreshModuleCalls'; export class ModuleCallsFeature implements StaticFeature { - private disposables: vscode.Disposable[] = []; - constructor( + private context: vscode.ExtensionContext, private client: BaseLanguageClient, private view: ModuleCallsDataProvider, ) {} @@ -34,30 +33,33 @@ export class ModuleCallsFeature implements StaticFeature { } public fillClientCapabilities(capabilities: ClientCapabilities & ExperimentalClientCapabilities): void { - if (!capabilities['experimental']) { - capabilities['experimental'] = {}; + if (!capabilities.experimental) { + capabilities.experimental = {}; } - capabilities['experimental']['refreshModuleCallsCommandId'] = CLIENT_MODULE_CALLS_CMD_ID; + capabilities.experimental.refreshModuleCallsCommandId = CLIENT_MODULE_CALLS_CMD_ID; } - public async initialize(capabilities: ServerCapabilities): Promise { - this.disposables.push(vscode.window.registerTreeDataProvider('terraform.modules', this.view)); + public initialize(capabilities: ServerCapabilities): void { + this.context.subscriptions.push(vscode.window.registerTreeDataProvider('terraform.modules', this.view)); if (!capabilities.experimental?.refreshModuleCalls) { console.log('Server does not support client.refreshModuleCalls'); - await vscode.commands.executeCommand('setContext', 'terraform.modules.supported', false); + vscode.commands.executeCommand('setContext', 'terraform.modules.supported', false); return; } - await vscode.commands.executeCommand('setContext', 'terraform.modules.supported', true); + vscode.commands.executeCommand('setContext', 'terraform.modules.supported', true); const d = this.client.onRequest(CLIENT_MODULE_CALLS_CMD_ID, () => { - this.view?.refresh(); + this.view.refresh(); }); - this.disposables.push(d); + + this.context.subscriptions.push(d); + + return; } public dispose(): void { - this.disposables.forEach((d: vscode.Disposable) => d.dispose()); + // } } diff --git a/src/features/moduleProviders.ts b/src/features/moduleProviders.ts index d76de509a5..64da74fd72 100644 --- a/src/features/moduleProviders.ts +++ b/src/features/moduleProviders.ts @@ -17,9 +17,8 @@ import { ExperimentalClientCapabilities } from './types'; export const CLIENT_MODULE_PROVIDERS_CMD_ID = 'client.refreshModuleProviders'; export class ModuleProvidersFeature implements StaticFeature { - private disposables: vscode.Disposable[] = []; - constructor( + private context: vscode.ExtensionContext, private client: BaseLanguageClient, private view: ModuleProvidersDataProvider, ) {} @@ -34,30 +33,30 @@ export class ModuleProvidersFeature implements StaticFeature { } public fillClientCapabilities(capabilities: ClientCapabilities & ExperimentalClientCapabilities): void { - if (!capabilities['experimental']) { - capabilities['experimental'] = {}; + if (!capabilities.experimental) { + capabilities.experimental = {}; } - capabilities['experimental']['refreshModuleProvidersCommandId'] = CLIENT_MODULE_PROVIDERS_CMD_ID; + capabilities.experimental.refreshModuleProvidersCommandId = CLIENT_MODULE_PROVIDERS_CMD_ID; } - public async initialize(capabilities: ServerCapabilities): Promise { - this.disposables.push(vscode.window.registerTreeDataProvider('terraform.providers', this.view)); + public initialize(capabilities: ServerCapabilities): void { + this.context.subscriptions.push(vscode.window.registerTreeDataProvider('terraform.providers', this.view)); if (!capabilities.experimental?.refreshModuleProviders) { console.log("Server doesn't support client.refreshModuleProviders"); - await vscode.commands.executeCommand('setContext', 'terraform.providers.supported', false); + vscode.commands.executeCommand('setContext', 'terraform.providers.supported', false); return; } - await vscode.commands.executeCommand('setContext', 'terraform.providers.supported', true); + vscode.commands.executeCommand('setContext', 'terraform.providers.supported', true); const d = this.client.onRequest(CLIENT_MODULE_PROVIDERS_CMD_ID, () => { - this.view?.refresh(); + this.view.refresh(); }); - this.disposables.push(d); + this.context.subscriptions.push(d); } public dispose(): void { - this.disposables.forEach((d: vscode.Disposable) => d.dispose()); + // } } diff --git a/src/features/semanticTokens.ts b/src/features/semanticTokens.ts index 58fab4d5f3..35255a6d76 100644 --- a/src/features/semanticTokens.ts +++ b/src/features/semanticTokens.ts @@ -38,7 +38,7 @@ export class CustomSemanticTokens implements StaticFeature { } public fillClientCapabilities(capabilities: ClientCapabilities): void { - if (!capabilities.textDocument || !capabilities.textDocument.semanticTokens) { + if (!capabilities.textDocument?.semanticTokens) { return; } diff --git a/src/features/showReferences.ts b/src/features/showReferences.ts index 86e354a863..0ccb002d01 100644 --- a/src/features/showReferences.ts +++ b/src/features/showReferences.ts @@ -17,14 +17,14 @@ import { config } from '../utils/vscode'; import { ExperimentalClientCapabilities } from './types'; -type Position = { +interface Position { line: number; character: number; -}; +} -type RefContext = { +interface RefContext { includeDeclaration: boolean; -}; +} const CLIENT_CMD_ID = 'client.showReferences'; const VSCODE_SHOW_REFERENCES = 'editor.action.showReferences'; @@ -45,13 +45,13 @@ export class ShowReferencesFeature implements StaticFeature { } public fillClientCapabilities(capabilities: ClientCapabilities & ExperimentalClientCapabilities): void { - if (this.isEnabled === false) { + if (!this.isEnabled) { return; } - if (!capabilities['experimental']) { - capabilities['experimental'] = {}; + if (!capabilities.experimental) { + capabilities.experimental = {}; } - capabilities['experimental']['showReferencesCommandId'] = CLIENT_CMD_ID; + capabilities.experimental.showReferencesCommandId = CLIENT_CMD_ID; } public initialize(capabilities: ServerCapabilities): void { @@ -59,13 +59,13 @@ export class ShowReferencesFeature implements StaticFeature { return; } - if (this.isEnabled === false) { + if (!this.isEnabled) { return; } const showRefs = vscode.commands.registerCommand(CLIENT_CMD_ID, async (pos: Position, refCtx: RefContext) => { const client = this._client; - const doc = vscode.window?.activeTextEditor?.document; + const doc = vscode.window.activeTextEditor?.document; if (!doc) { return; } diff --git a/src/features/telemetry.ts b/src/features/telemetry.ts index 1b0043243c..02197a42cd 100644 --- a/src/features/telemetry.ts +++ b/src/features/telemetry.ts @@ -11,16 +11,15 @@ import { ExperimentalClientCapabilities } from './types'; const TELEMETRY_VERSION = 1; -type TelemetryEvent = { +interface TelemetryEvent { v: number; name: string; - properties: { [key: string]: unknown }; -}; + properties: Record; +} export class TelemetryFeature implements StaticFeature { - private disposables: vscode.Disposable[] = []; - constructor( + private context: vscode.ExtensionContext, private client: BaseLanguageClient, private reporter: TelemetryReporter, ) {} @@ -35,21 +34,21 @@ export class TelemetryFeature implements StaticFeature { } public fillClientCapabilities(capabilities: ClientCapabilities & ExperimentalClientCapabilities): void { - if (!capabilities['experimental']) { - capabilities['experimental'] = {}; + if (!capabilities.experimental) { + capabilities.experimental = {}; } - capabilities['experimental']['telemetryVersion'] = TELEMETRY_VERSION; + capabilities.experimental.telemetryVersion = TELEMETRY_VERSION; } public initialize(): void { - if (vscode.env.isTelemetryEnabled === false) { + if (!vscode.env.isTelemetryEnabled) { return; } - this.disposables.push( + this.context.subscriptions.push( this.client.onTelemetry((event: TelemetryEvent) => { if (event.v !== TELEMETRY_VERSION) { - console.log(`unsupported telemetry event: ${event}`); + console.log(`unsupported telemetry event: ${event.name}`); return; } @@ -59,6 +58,6 @@ export class TelemetryFeature implements StaticFeature { } public dispose(): void { - this.disposables.forEach((d: vscode.Disposable) => d.dispose()); + // } } diff --git a/src/features/terraformCloud.ts b/src/features/terraformCloud.ts index c3818c4463..d452016064 100644 --- a/src/features/terraformCloud.ts +++ b/src/features/terraformCloud.ts @@ -40,12 +40,12 @@ export class TerraformCloudFeature implements vscode.Disposable { this.statusBar = new OrganizationStatusBar(context); authProvider.onDidChangeSessions(async (event) => { - if (event && event.added && event.added.length > 0) { + if (event.added && event.added.length > 0) { await vscode.commands.executeCommand('terraform.cloud.organization.picker'); - this.statusBar.show(); + await this.statusBar.show(); } - if (event && event.removed && event.removed.length > 0) { - this.statusBar.reset(); + if (event.removed && event.removed.length > 0) { + await this.statusBar.reset(); } }); @@ -96,7 +96,7 @@ export class TerraformCloudFeature implements vscode.Disposable { showCollapseAll: true, treeDataProvider: workspaceDataProvider, }); - const organization = this.context.workspaceState.get('terraform.cloud.organization', ''); + const organization: string = this.context.workspaceState.get('terraform.cloud.organization', ''); workspaceView.title = organization !== '' ? `Workspaces - (${organization})` : 'Workspaces'; this.context.subscriptions.push( @@ -141,7 +141,7 @@ export class TerraformCloudFeature implements vscode.Disposable { workspaceView.onDidChangeVisibility(async (event) => { if (event.visible) { // the view is visible so show the status bar - this.statusBar.show(); + await this.statusBar.show(); await vscode.commands.executeCommand('setContext', 'terraform.cloud.views.visible', true); } else { // hide statusbar because user isn't looking at our views @@ -153,7 +153,7 @@ export class TerraformCloudFeature implements vscode.Disposable { this.context.subscriptions.push( vscode.commands.registerCommand('terraform.cloud.workspaces.picker', async () => { this.reporter.sendTelemetryEvent('tfc-new-workspace'); - const organization = this.context.workspaceState.get('terraform.cloud.organization', ''); + const organization: string = this.context.workspaceState.get('terraform.cloud.organization', ''); if (organization === '') { return []; } @@ -167,7 +167,7 @@ export class TerraformCloudFeature implements vscode.Disposable { const organizationQuickPick = new APIQuickPick(organizationAPIResource); let choice: vscode.QuickPickItem | undefined; - // eslint-disable-next-line no-constant-condition + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition while (true) { choice = await organizationQuickPick.pick(false); @@ -178,7 +178,7 @@ export class TerraformCloudFeature implements vscode.Disposable { this.reporter.sendTelemetryEvent('tfc-pick-organization-create'); // open the browser an re-run the loop - choice.open(); + await choice.open(); continue; } else if (choice instanceof RefreshOrganizationItem) { this.reporter.sendTelemetryEvent('tfc-pick-organization-refresh'); @@ -191,7 +191,7 @@ export class TerraformCloudFeature implements vscode.Disposable { // user chose an organization so update the statusbar and make sure its visible organizationQuickPick.hide(); - this.statusBar.show(choice.label); + await this.statusBar.show(choice.label); workspaceView.title = `Workspace - (${choice.label})`; // project filter should be cleared on org change diff --git a/src/features/terraformVersion.ts b/src/features/terraformVersion.ts index eff2b35971..8b2676fb70 100644 --- a/src/features/terraformVersion.ts +++ b/src/features/terraformVersion.ts @@ -16,11 +16,10 @@ import * as versionStatus from '../status/installedVersion'; import * as requiredVersionStatus from '../status/requiredVersion'; export class TerraformVersionFeature implements StaticFeature { - private disposables: vscode.Disposable[] = []; - private clientTerraformVersionCommandId = 'client.refreshTerraformVersion'; constructor( + private context: vscode.ExtensionContext, private client: LanguageClient, private reporter: TelemetryReporter, private outputChannel: vscode.OutputChannel, @@ -40,7 +39,7 @@ export class TerraformVersionFeature implements StaticFeature { capabilities.experimental.refreshTerraformVersionCommandId = this.clientTerraformVersionCommandId; } - public async initialize(capabilities: ServerCapabilities): Promise { + public initialize(capabilities: ServerCapabilities): void { if (!capabilities.experimental?.refreshTerraformVersion) { this.outputChannel.appendLine("Server doesn't support client.refreshTerraformVersion"); return; @@ -61,8 +60,8 @@ export class TerraformVersionFeature implements StaticFeature { lsStatus.setLanguageServerBusy(); const response = await terraform.terraformVersion(moduleDir.toString(), this.client, this.reporter); - versionStatus.setVersion(response.discovered_version || 'unknown'); - requiredVersionStatus.setVersion(response.required_version || 'any'); + versionStatus.setVersion(response.discovered_version ?? 'unknown'); + requiredVersionStatus.setVersion(response.required_version ?? 'any'); lsStatus.setLanguageServerRunning(); versionStatus.setReady(); @@ -90,13 +89,10 @@ export class TerraformVersionFeature implements StaticFeature { } }); - this.disposables.push(handler); + this.context.subscriptions.push(handler); } public dispose(): void { - this.disposables.forEach((d: vscode.Disposable, index, things) => { - d.dispose(); - things.splice(index, 1); - }); + // } } diff --git a/src/providers/terraform/moduleCalls.ts b/src/providers/terraform/moduleCalls.ts index 61415f3f6e..1f21ce606d 100644 --- a/src/providers/terraform/moduleCalls.ts +++ b/src/providers/terraform/moduleCalls.ts @@ -26,10 +26,10 @@ class ModuleCallItem extends vscode.TreeItem { children.length >= 1 ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None, ); - this.description = this.version ? `${this.version}` : ''; + this.description = this.version ? this.version : ''; if (this.version === undefined) { - this.tooltip = `${this.sourceAddr}`; + this.tooltip = this.sourceAddr; } else { this.tooltip = `${this.sourceAddr}@${this.version}`; } @@ -59,11 +59,10 @@ class ModuleCallItem extends vscode.TreeItem { } export class ModuleCallsDataProvider implements vscode.TreeDataProvider { - private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< - ModuleCallItem | undefined | null | void + private _onDidChangeTreeData: vscode.EventEmitter = new vscode.EventEmitter< + ModuleCallItem | undefined | null >(); - readonly onDidChangeTreeData: vscode.Event = - this._onDidChangeTreeData.event; + readonly onDidChangeTreeData: vscode.Event = this._onDidChangeTreeData.event; private svg = ''; @@ -75,13 +74,15 @@ export class ModuleCallsDataProvider implements vscode.TreeDataProvider this.refresh()), + vscode.commands.registerCommand('terraform.modules.refreshList', () => { + this.refresh(); + }), vscode.commands.registerCommand('terraform.modules.openDocumentation', (module: ModuleCallItem) => { if (module.docsLink) { vscode.env.openExternal(vscode.Uri.parse(module.docsLink)); } }), - vscode.window.onDidChangeActiveTextEditor(async () => { + vscode.window.onDidChangeActiveTextEditor(() => { // most of the time this is called when the user switches tabs or closes the file // we already check for state inside the getModule function, so we can just call refresh here this.refresh(); @@ -90,7 +91,7 @@ export class ModuleCallsDataProvider implements vscode.TreeDataProvider { @@ -127,11 +128,11 @@ export class ModuleCallsDataProvider implements vscode.TreeDataProvider { - private readonly didChangeTreeData = new vscode.EventEmitter(); + private readonly didChangeTreeData = new vscode.EventEmitter(); public readonly onDidChangeTreeData = this.didChangeTreeData.event; constructor( @@ -40,8 +40,10 @@ export class ModuleProvidersDataProvider implements vscode.TreeDataProvider this.refresh()), - vscode.window.onDidChangeActiveTextEditor(async () => { + vscode.commands.registerCommand('terraform.providers.refreshList', () => { + this.refresh(); + }), + vscode.window.onDidChangeActiveTextEditor(() => { // most of the time this is called when the user switches tabs or closes the file // we already check for state inside the getprovider function, so we can just call refresh here this.refresh(); @@ -55,7 +57,7 @@ export class ModuleProvidersDataProvider implements vscode.TreeDataProvider { @@ -91,11 +93,11 @@ export class ModuleProvidersDataProvider implements vscode.TreeDataProvider, vscode.Disposable { - private readonly didChangeTreeData = new vscode.EventEmitter(); + private readonly didChangeTreeData = new vscode.EventEmitter(); public readonly onDidChangeTreeData = this.didChangeTreeData.event; private apply: ApplyTreeItem | undefined; @@ -37,14 +37,14 @@ export class ApplyTreeDataProvider implements vscode.TreeDataProvider { return element; } - getChildren(element?: vscode.TreeItem | undefined): vscode.ProviderResult { + getChildren(element?: vscode.TreeItem): vscode.ProviderResult { if (!this.apply) { return []; } @@ -52,7 +52,7 @@ export class ApplyTreeDataProvider implements vscode.TreeDataProvider 0) { + if (applyLog?.outputs && Object.keys(applyLog.outputs).length > 0) { items.push(new OutputsItem(applyLog.outputs)); } - if (applyLog && applyLog.diagnostics && applyLog.diagnosticSummary && applyLog.diagnostics.length > 0) { + if (applyLog?.diagnostics && applyLog.diagnosticSummary && applyLog.diagnostics.length > 0) { items.push(new DiagnosticsItem(applyLog.diagnostics, applyLog.diagnosticSummary)); } return items; @@ -139,7 +139,7 @@ export class ApplyTreeDataProvider implements vscode.TreeDataProvider { + this.secretStorage.onDidChange(async (e) => { if (e.key === this.sessionKey) { - this.checkForUpdates(); + await this.checkForUpdates(); } }), ); @@ -166,7 +166,7 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati // This function is called first when `vscode.authentication.getSessions` is called. // eslint-disable-next-line @typescript-eslint/no-unused-vars - async getSessions(scopes?: string[] | undefined): Promise { + async getSessions(scopes?: string[]): Promise { try { let session = await this.sessionPromise; if (!session) { @@ -174,7 +174,7 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati return []; } - if (session.hostName === '' || session.hostName === undefined) { + if (session.hostName === '') { // we have a valid session but the hostname is not set // this is most likely an old session that needs to be updated // if hostname is undefined, we need to set it to the default @@ -309,16 +309,16 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati for (const key of tfcCredentials.keys()) { setupPingClient(key); const instance = await pingClient.ping(); - if (!instance) { - continue; - } + // if (!instance) { + // continue; + // } hostnames.push({ detail: key, label: `${instance.appName} instance`, }); } - } catch (error) { + } catch { // If there is an error, it's likely that the credential file is not present // or there is an issue with the file itself // In this case, we'll just continue with just the default hostname @@ -441,7 +441,7 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati process.platform === 'win32' ? path.join(os.homedir(), 'AppData', 'Roaming', 'terraform.d', 'credentials.tfrc.json') : path.join(os.homedir(), '.terraform.d', 'credentials.tfrc.json'); - if ((await this.pathExists(credFilePath)) === false) { + if (!(await this.pathExists(credFilePath))) { throw new TerraformCredentialFileError( 'Terraform credential file not found. Please login using the Terraform CLI and try again.', ); @@ -451,7 +451,7 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati let text: string; try { text = Buffer.from(content).toString('utf8'); - } catch (error) { + } catch { throw new TerraformCredentialFileError( 'Failed to read configuration file. Please login using the Terraform CLI and try again', ); @@ -461,7 +461,7 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati try { const data = JSON.parse(text); return new Map(Object.entries(data.credentials)); - } catch (error) { + } catch { throw new TerraformCredentialFileError( `Failed to parse configuration file. Please login using the Terraform CLI and try again`, ); @@ -486,7 +486,7 @@ export class TerraformCloudAuthenticationProvider implements vscode.Authenticati try { await vscode.workspace.fs.stat(vscode.Uri.file(filePath)); return true; - } catch (error) { + } catch { return false; } } diff --git a/src/providers/tfc/logHelpers.ts b/src/providers/tfc/logHelpers.ts index f185ce57a0..aca8206f83 100644 --- a/src/providers/tfc/logHelpers.ts +++ b/src/providers/tfc/logHelpers.ts @@ -38,13 +38,14 @@ export class OutputsItem extends vscode.TreeItem implements ItemWithChildren { class OutputChangeItem extends vscode.TreeItem { constructor(name: string, output: OutputChange) { super(name, vscode.TreeItemCollapsibleState.None); - this.id = 'output/' + output.action + '/' + name; if (output.action) { + this.id = 'output/' + output.action + '/' + name; this.iconPath = GetChangeActionIcon(output.action); - } - this.description = output.action; - if (output.sensitive) { - this.description += ' (sensitive)'; + + this.description = output.action; + if (output.sensitive) { + this.description += ' (sensitive)'; + } } } } diff --git a/src/providers/tfc/organizationPicker.ts b/src/providers/tfc/organizationPicker.ts index bcab00ac03..6785a5d1c8 100644 --- a/src/providers/tfc/organizationPicker.ts +++ b/src/providers/tfc/organizationPicker.ts @@ -91,12 +91,12 @@ export class OrganizationAPIResource implements APIResource { let message = 'Failed to fetch organizations'; if (error instanceof ZodiosError) { - handleZodiosError(error, message, this.outputChannel, this.reporter); + await handleZodiosError(error, message, this.outputChannel, this.reporter); return picks; } if (axios.isAxiosError(error) && error.response?.status === 401) { - handleAuthError(); + await handleAuthError(); return picks; } else if (isErrorFromAlias(apiClient.api, 'listOrganizations', error)) { message += apiErrorsToString(error.response.data.errors); diff --git a/src/providers/tfc/planProvider.ts b/src/providers/tfc/planProvider.ts index 055646f2dc..506906bf37 100644 --- a/src/providers/tfc/planProvider.ts +++ b/src/providers/tfc/planProvider.ts @@ -18,7 +18,7 @@ import { PlanTreeItem } from './runProvider'; import { DiagnosticSummary, DiagnosticsItem, OutputsItem, isItemWithChildren, ItemWithChildren } from './logHelpers'; export class PlanTreeDataProvider implements vscode.TreeDataProvider, vscode.Disposable { - private readonly didChangeTreeData = new vscode.EventEmitter(); + private readonly didChangeTreeData = new vscode.EventEmitter(); public readonly onDidChangeTreeData = this.didChangeTreeData.event; private plan: PlanTreeItem | undefined; @@ -37,14 +37,14 @@ export class PlanTreeDataProvider implements vscode.TreeDataProvider { return element; } - getChildren(element?: vscode.TreeItem | undefined): vscode.ProviderResult { + getChildren(element?: vscode.TreeItem): vscode.ProviderResult { if (!this.plan) { return []; } @@ -52,7 +52,7 @@ export class PlanTreeDataProvider implements vscode.TreeDataProvider 0) { + if (planLog?.diagnostics && planLog.diagnosticSummary && planLog.diagnostics.length > 0) { items.push(new DiagnosticsItem(planLog.diagnostics, planLog.diagnosticSummary)); } return items; @@ -161,7 +161,7 @@ export class PlanTreeDataProvider implements vscode.TreeDataProvider, vscode.Disposable { - private readonly didChangeTreeData = new vscode.EventEmitter(); + private readonly didChangeTreeData = new vscode.EventEmitter(); public readonly onDidChangeTreeData = this.didChangeTreeData.event; private activeWorkspace: WorkspaceTreeItem | undefined; @@ -36,7 +36,7 @@ export class RunTreeDataProvider implements vscode.TreeDataProvider { - this.downloadPlanLog(run); + await this.downloadPlanLog(run); }), vscode.commands.registerCommand('terraform.cloud.run.apply.downloadLog', async (run: ApplyTreeItem) => this.downloadApplyLog(run), @@ -72,14 +72,14 @@ export class RunTreeDataProvider implements vscode.TreeDataProvider { return element; } - getChildren(element?: TFCRunTreeItem | undefined): vscode.ProviderResult { + getChildren(element?: TFCRunTreeItem): vscode.ProviderResult { if (!this.activeWorkspace || !(this.activeWorkspace instanceof WorkspaceTreeItem)) { return []; } @@ -91,7 +91,7 @@ export class RunTreeDataProvider implements vscode.TreeDataProvider { - const organization = this.ctx.workspaceState.get('terraform.cloud.organization', ''); + const organization: string = this.ctx.workspaceState.get('terraform.cloud.organization', ''); if (organization === '') { return []; } @@ -144,8 +144,7 @@ export class RunTreeDataProvider implements vscode.TreeDataProvider this.fetchResource.apply(this), 300); } @@ -49,8 +51,8 @@ export class APIQuickPick { await this.fetchResource(); const result = await new Promise((c) => { - this.quickPick.onDidAccept(() => c(this.quickPick.selectedItems[0])); - this.quickPick.onDidHide(() => c(undefined)); + this.quickPick.onDidAccept(() => { c(this.quickPick.selectedItems[0]); }); + this.quickPick.onDidHide(() => { c(undefined); }); this.quickPick.show(); }); diff --git a/src/providers/tfc/workspaceFilters.ts b/src/providers/tfc/workspaceFilters.ts index 507757bea8..2b3ea5a6e9 100644 --- a/src/providers/tfc/workspaceFilters.ts +++ b/src/providers/tfc/workspaceFilters.ts @@ -71,12 +71,12 @@ export class ProjectsAPIResource implements APIResource { let message = 'Failed to fetch projects'; if (error instanceof ZodiosError) { - handleZodiosError(error, message, this.outputChannel, this.reporter); + await handleZodiosError(error, message, this.outputChannel, this.reporter); return picks; } if (axios.isAxiosError(error) && error.response?.status === 401) { - handleAuthError(); + await handleAuthError(); return picks; } else if (isErrorFromAlias(apiClient.api, 'listProjects', error)) { message += apiErrorsToString(error.response.data.errors); diff --git a/src/providers/tfc/workspaceProvider.ts b/src/providers/tfc/workspaceProvider.ts index 4798c96cfd..1fb06c772b 100644 --- a/src/providers/tfc/workspaceProvider.ts +++ b/src/providers/tfc/workspaceProvider.ts @@ -19,7 +19,7 @@ import axios from 'axios'; import { apiErrorsToString } from '../../api/terraformCloud/errors'; export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider, vscode.Disposable { - private readonly didChangeTreeData = new vscode.EventEmitter(); + private readonly didChangeTreeData = new vscode.EventEmitter(); public readonly onDidChangeTreeData = this.didChangeTreeData.event; private projectFilter: string | undefined; private pageSize = 50; @@ -60,11 +60,11 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider { + vscode.commands.registerCommand('terraform.cloud.workspaces.filterByProject', async () => { this.reporter.sendTelemetryEvent('tfc-workspaces-filter'); - this.filterByProject(); + await this.filterByProject(); }), - vscode.commands.registerCommand('terraform.cloud.workspaces.loadMore', async () => { + vscode.commands.registerCommand('terraform.cloud.workspaces.loadMore', () => { this.reporter.sendTelemetryEvent('tfc-workspaces-loadMore'); this.refresh(); this.runDataProvider.refresh(); @@ -73,7 +73,7 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider { if (element) { - return [element]; + return [element as vscode.TreeItem]; } return this.buildChildren(); @@ -124,7 +124,7 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider { - const organization = this.ctx.workspaceState.get('terraform.cloud.organization', ''); + const organization: string = this.ctx.workspaceState.get('terraform.cloud.organization', ''); if (organization === '') { return []; } @@ -208,10 +208,8 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider p.id === workspace.relationships['project']?.data?.id); + for (const workspace of workspaces) { + const project = projects.find((p) => p.id === workspace.relationships.project?.data?.id); const projectName = project ? project.attributes.name : ''; const lastRunId = workspace.relationships['latest-run']?.data?.id; @@ -237,13 +235,13 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider { const socket = new net.Socket(); socket.connect({ diff --git a/src/utils/serverPath.ts b/src/utils/serverPath.ts index 31ff6e7368..7beecc72c9 100644 --- a/src/utils/serverPath.ts +++ b/src/utils/serverPath.ts @@ -60,7 +60,9 @@ export class ServerPath { if (this.customBinPath) { extraHint = `. Check "terraform.languageServer.path" in your settings.`; } - throw new Error(`Unable to launch language server: ${err instanceof Error ? err.message : err}${extraHint}`); + throw new Error( + `Unable to launch language server: ${err instanceof Error ? err.message : (err as string)}${extraHint}`, + ); } return cmd; From 1da786553665bd8bb5f94daca29b20d2f80d65cc Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 15:55:46 -0400 Subject: [PATCH 5/8] extension eslint fixes --- src/extension.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 75710005d2..1cf7796371 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -208,11 +208,11 @@ export async function activate(context: vscode.ExtensionContext): Promise client.registerFeatures([ new LanguageStatusFeature(client, reporter, outputChannel), new CustomSemanticTokens(client, manifest), - new ModuleProvidersFeature(client, new ModuleProvidersDataProvider(context, client, reporter)), - new ModuleCallsFeature(client, new ModuleCallsDataProvider(context, client, reporter)), - new TelemetryFeature(client, reporter), + new ModuleProvidersFeature(context, client, new ModuleProvidersDataProvider(context, client, reporter)), + new ModuleCallsFeature(context, client, new ModuleCallsDataProvider(context, client, reporter)), + new TelemetryFeature(context, client, reporter), new ShowReferencesFeature(client), - new TerraformVersionFeature(client, reporter, outputChannel), + new TerraformVersionFeature(context, client, reporter, outputChannel), ]); // these need the LS to function, so are only registered if enabled From 30de3c3bdf1c3a392c021202f944455e1ece270a Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 15:56:04 -0400 Subject: [PATCH 6/8] convert esbuild to mjs --- esbuild.js => esbuild.mjs | 20 +++++++++++++------- package.json | 8 ++++---- 2 files changed, 17 insertions(+), 11 deletions(-) rename esbuild.js => esbuild.mjs (86%) diff --git a/esbuild.js b/esbuild.mjs similarity index 86% rename from esbuild.js rename to esbuild.mjs index 36f0972cb2..4b6d858c02 100644 --- a/esbuild.js +++ b/esbuild.mjs @@ -3,14 +3,20 @@ * SPDX-License-Identifier: MPL-2.0 */ - -const esbuild = require('esbuild'); -const glob = require('glob'); -const path = require('path'); -const polyfill = require('@esbuild-plugins/node-globals-polyfill'); + +import { context } from 'esbuild'; +import { glob } from 'glob'; +import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'; +import path from 'node:path'; +import process from 'node:process'; +import console from 'node:console'; +import { fileURLToPath } from 'node:url'; const production = process.argv.includes('--production'); const watch = process.argv.includes('--watch'); +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + /** * @type {import('esbuild').Plugin} @@ -89,7 +95,7 @@ async function main() { global: 'globalThis', }, plugins: [ - polyfill.NodeGlobalsPolyfillPlugin({ + NodeGlobalsPolyfillPlugin({ process: true, buffer: true, }), @@ -99,7 +105,7 @@ async function main() { ...defaults, }; - const contexts = [await esbuild.context(desktop), await esbuild.context(web)]; + const contexts = [await context(desktop), await context(web)]; try { const promises = []; diff --git a/package.json b/package.json index 34fcf8a041..7ffb05580f 100644 --- a/package.json +++ b/package.json @@ -929,15 +929,15 @@ }, "scripts": { "prepare": "npm run download:artifacts && cd src/test/e2e && npm install", - "compile": "npm run check-types && npm run lint && node esbuild.js", - "compile:prod": "npm run check-types && npm run lint && node esbuild.js --production", + "compile": "npm run check-types && npm run lint && node esbuild.mjs", + "compile:prod": "npm run check-types && npm run lint && node esbuild.mjs --production", "compile:tests": "tsc -p .", "watch": "npm-run-all -p watch:esbuild watch:tsc", - "watch:esbuild": "node esbuild.js --watch", + "watch:esbuild": "node esbuild.mjs --watch", "watch:tsc": "tsc --noEmit --watch", "watch:tests": "tsc -p . -w", "watch:web": "npm-run-all -p watch:web:*", - "watch:web:esbuild": "node esbuild.js --watch", + "watch:web:esbuild": "node esbuild.mjs --watch", "watch:web:tsc": "tsc --noEmit --watch", "web": "npm run compile && vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./src/test/fixtures", "web:serve": "npx serve --cors -l 5001", From ee2a902ae431ea932bc5fc8c76ab98dfc3783faf Mon Sep 17 00:00:00 2001 From: James Pogran Date: Fri, 20 Sep 2024 15:58:47 -0400 Subject: [PATCH 7/8] convert downloader to mjs --- build/{downloader.ts => downloader.mjs} | 43 +++++++++++++------------ package.json | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) rename build/{downloader.ts => downloader.mjs} (85%) diff --git a/build/downloader.ts b/build/downloader.mjs similarity index 85% rename from build/downloader.ts rename to build/downloader.mjs index 69eb51083f..7adc365c77 100644 --- a/build/downloader.ts +++ b/build/downloader.mjs @@ -3,17 +3,24 @@ * SPDX-License-Identifier: MPL-2.0 */ -import * as fs from 'fs'; -import * as path from 'path'; import * as releases from '@hashicorp/js-releases'; import axios from 'axios'; +import { Buffer } from 'buffer'; +import * as fs from 'fs'; +import console from 'node:console'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; -async function fileFromUrl(url: string): Promise { +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +async function fileFromUrl(url) { const response = await axios.get(url, { responseType: 'arraybuffer' }); return Buffer.from(response.data, 'binary'); } -function getPlatform(platform: string) { +function getPlatform(platform) { if (platform === 'win32') { return 'windows'; } @@ -23,7 +30,7 @@ function getPlatform(platform: string) { return platform; } -function getArch(arch: string) { +function getArch(arch) { // platform | terraform-ls | extension platform | vs code editor // -- | -- | -- | -- // macOS | darwin_amd64 | darwin_x64 | ✅ @@ -42,17 +49,11 @@ function getArch(arch: string) { return arch; } -interface ExtensionInfo { - name: string; - extensionVersion: string; - languageServerVersion: string; - preview: false; - syntaxVersion: string; -} - -function getExtensionInfo(): ExtensionInfo { - // eslint-disable-next-line @typescript-eslint/no-var-requires - const pjson = require('../package.json'); +function getExtensionInfo() { + const cwd = path.resolve(__dirname); + const buildDir = path.basename(cwd); + const repoDir = cwd.replace(buildDir, ''); + const pjson = JSON.parse(fs.readFileSync(path.join(repoDir, 'package.json'))); return { name: pjson.name, extensionVersion: pjson.version, @@ -62,7 +63,7 @@ function getExtensionInfo(): ExtensionInfo { }; } -async function downloadLanguageServer(platform: string, architecture: string, extInfo: ExtensionInfo) { +async function downloadLanguageServer(platform, architecture, extInfo) { const cwd = path.resolve(__dirname); const buildDir = path.basename(cwd); @@ -108,7 +109,7 @@ async function downloadLanguageServer(platform: string, architecture: string, ex }); } -async function downloadFile(url: string, installPath: string) { +async function downloadFile(url, installPath) { if (process.env.downloader_log === 'true') { console.log(`Downloading: ${url}`); } @@ -120,7 +121,7 @@ async function downloadFile(url: string, installPath: string) { } } -async function downloadSyntax(info: ExtensionInfo) { +async function downloadSyntax(info) { const release = `v${info.syntaxVersion}`; const cwd = path.resolve(__dirname); @@ -148,7 +149,7 @@ async function downloadSyntax(info: ExtensionInfo) { await downloadFile(url, path.join(installPath, hclSyntaxFile)); } -async function run(platform: string, architecture: string) { +async function run(platform, architecture) { const extInfo = getExtensionInfo(); if (process.env.downloader_log === 'true') { console.log(extInfo); @@ -175,7 +176,7 @@ if (lsTarget !== undefined) { const tgt = lsTarget.split('_'); os = tgt[0]; - arch = tgt[1] as NodeJS.Architecture; + arch = tgt[1]; } run(os, arch); diff --git a/package.json b/package.json index 7ffb05580f..f10cb5c4bb 100644 --- a/package.json +++ b/package.json @@ -942,7 +942,7 @@ "web": "npm run compile && vscode-test-web --browserType=chromium --extensionDevelopmentPath=. ./src/test/fixtures", "web:serve": "npx serve --cors -l 5001", "web:tunnel": "npx localtunnel -p 5001", - "download:artifacts": "ts-node ./build/downloader.ts", + "download:artifacts": "node ./build/downloader.mjs", "vscode:prepublish": "npm run compile:prod", "package": "vsce package", "pretest": "npm run compile:tests && npm run compile && npm run lint", From f5e4f2dae6686c85ae01315ed2d2aa5dcb194f8d Mon Sep 17 00:00:00 2001 From: "hashicorp-copywrite[bot]" <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Date: Fri, 20 Sep 2024 20:27:26 +0000 Subject: [PATCH 8/8] [COMPLIANCE] Add required copyright headers Signed-off-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> --- eslint.config.mjs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index 56db239a1b..56d9e0b8b4 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,3 +1,8 @@ +/** + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + import pluginJs from '@eslint/js'; import prettierConfig from 'eslint-config-prettier'; import globals from 'globals';