diff --git a/package-lock.json b/package-lock.json index 0e2d419e26..a38e619e7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-home-assistant", - "version": "1.41.3", + "version": "1.42.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "vscode-home-assistant", - "version": "1.41.3", + "version": "1.42.0", "license": "MIT", "dependencies": { "axios": "^1.7.7", @@ -25,7 +25,7 @@ "yaml-language-server": "0.12.0" }, "devDependencies": { - "@types/mocha": "10.0.6", + "@types/mocha": "10.0.8", "@types/node": "20.4.8", "@types/request": "2.48.12", "@types/vscode": "1.45.1", @@ -445,9 +445,9 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz", + "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", "dev": true }, "node_modules/@types/node": { @@ -5074,9 +5074,9 @@ "dev": true }, "@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "version": "10.0.8", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz", + "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", "dev": true }, "@types/node": { diff --git a/package.json b/package.json index 5c128bc023..f244dba6ab 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-home-assistant", "displayName": "Home Assistant Config Helper", "description": " Completion for entity-id's in Home Assistant Configurations", - "version": "1.41.3", + "version": "1.42.0", "preview": false, "engines": { "vscode": "^1.45.1" @@ -426,7 +426,7 @@ "prepare": "husky install" }, "devDependencies": { - "@types/mocha": "10.0.6", + "@types/mocha": "10.0.8", "@types/node": "20.4.8", "@types/request": "2.48.12", "@types/vscode": "1.45.1", diff --git a/src/language-service/package-lock.json b/src/language-service/package-lock.json index 1e016e6d47..c864db32dc 100644 --- a/src/language-service/package-lock.json +++ b/src/language-service/package-lock.json @@ -1,12 +1,12 @@ { "name": "home-assistant-language-service", - "version": "1.41.3", + "version": "1.42.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "home-assistant-language-service", - "version": "1.41.3", + "version": "1.42.0", "license": "MIT", "dependencies": { "axios": "^1.2.1", @@ -29,7 +29,7 @@ "eslint": "^7.4.0", "eslint-config-prettier": "^9.0.0", "prettier": "^3.0.0", - "rimraf": "5.0.5", + "rimraf": "6.0.1", "ts-loader": "^9.2.8", "ts-node": "10.9.2", "typescript": "5.6.2", @@ -185,9 +185,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true, "engines": { "node": ">=12" @@ -381,16 +381,6 @@ "node": ">= 8" } }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -1085,9 +1075,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -1982,9 +1972,9 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.0", @@ -2269,21 +2259,18 @@ "dev": true }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/jest-worker": { @@ -2501,9 +2488,9 @@ "dev": true }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -2572,6 +2559,12 @@ "node": ">= 0.8.0" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2609,28 +2602,28 @@ } }, "node_modules/path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, "dependencies": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", "dev": true, "engines": { - "node": "14 || >=16.14" + "node": "20 || >=22" } }, "node_modules/picocolors": { @@ -2810,18 +2803,19 @@ } }, "node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, "dependencies": { - "glob": "^10.3.7" + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" }, "bin": { "rimraf": "dist/esm/bin.mjs" }, "engines": { - "node": ">=14" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -2837,37 +2831,38 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4373,9 +4368,9 @@ }, "dependencies": { "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "dev": true }, "ansi-styles": { @@ -4527,13 +4522,6 @@ "fastq": "^1.6.0" } }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -5071,9 +5059,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "requires": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -5745,9 +5733,9 @@ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" }, "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -5970,13 +5958,12 @@ "dev": true }, "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz", + "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==", "dev": true, "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" + "@isaacs/cliui": "^8.0.2" } }, "jest-worker": { @@ -6157,9 +6144,9 @@ "dev": true }, "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true }, "mkdirp": { @@ -6219,6 +6206,12 @@ "word-wrap": "^1.2.3" } }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6247,19 +6240,19 @@ "dev": true }, "path-scurry": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", - "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "dev": true, "requires": { - "lru-cache": "^9.1.1 || ^10.0.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "dependencies": { "lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz", + "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==", "dev": true } } @@ -6384,12 +6377,13 @@ "dev": true }, "rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, "requires": { - "glob": "^10.3.7" + "glob": "^11.0.0", + "package-json-from-dist": "^1.0.0" }, "dependencies": { "brace-expansion": { @@ -6402,22 +6396,23 @@ } }, "glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz", + "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==", "dev": true, "requires": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^4.0.1", + "minimatch": "^10.0.0", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, "requires": { "brace-expansion": "^2.0.1" diff --git a/src/language-service/package.json b/src/language-service/package.json index 580c3aadfd..758406dd6a 100644 --- a/src/language-service/package.json +++ b/src/language-service/package.json @@ -1,6 +1,6 @@ { "name": "home-assistant-language-service", - "version": "1.41.3", + "version": "1.42.0", "description": "Home Assistant Language Service", "source": "src/haLanguageService.ts", "main": "dist/haLanguageService.js", @@ -48,7 +48,7 @@ "eslint": "^7.4.0", "eslint-config-prettier": "^9.0.0", "prettier": "^3.0.0", - "rimraf": "5.0.5", + "rimraf": "6.0.1", "ts-loader": "^9.2.8", "ts-node": "10.9.2", "typescript": "5.6.2", diff --git a/src/language-service/src/completionHelpers/areas.ts b/src/language-service/src/completionHelpers/areas.ts new file mode 100644 index 0000000000..a61d99859f --- /dev/null +++ b/src/language-service/src/completionHelpers/areas.ts @@ -0,0 +1,69 @@ +import { MarkedString } from "vscode-languageserver-protocol"; +import { + JSONWorkerContribution, + JSONPath, + CompletionsCollector, +} from "vscode-json-languageservice"; +import { IHaConnection } from "../home-assistant/haConnection"; + +export class AreaCompletionContribution implements JSONWorkerContribution { + public static propertyMatches: string[] = ["area_id", "area"]; + + constructor(private haConnection: IHaConnection) {} + + public collectDefaultCompletions( + resource: string, + result: CompletionsCollector, + ): Thenable { + return Promise.resolve(null); + } + + public collectPropertyCompletions = async ( + resource: string, + location: JSONPath, + currentWord: string, + addValue: boolean, + isLast: boolean, + result: CompletionsCollector, + ): Promise => { + if (location.length < 2) { + return; + } + const currentNode = location[location.length - 1]; + const parentNode = location[location.length - 2]; // in case or arrays, currentNode is the indexer for the array position + if ( + !AreaCompletionContribution.propertyMatches.some( + (x) => + x === currentNode || + (!Number.isNaN(+currentNode) && x === parentNode), + ) + ) { + return; + } + const areaCompletions = await this.haConnection.getAreaCompletions(); + areaCompletions.forEach((c) => result.add(c)); + }; + + public collectValueCompletions = async ( + resource: string, + location: JSONPath, + currentKey: string, + result: CompletionsCollector, + ): Promise => { + if ( + !AreaCompletionContribution.propertyMatches.some((x) => x === currentKey) + ) { + return; + } + + const areaCompletions = await this.haConnection.getAreaCompletions(); + areaCompletions.forEach((c) => result.add(c)); + }; + + public getInfoContribution( + resource: string, + location: JSONPath, + ): Thenable { + return Promise.resolve([]); + } +} diff --git a/src/language-service/src/completionHelpers/floors.ts b/src/language-service/src/completionHelpers/floors.ts new file mode 100644 index 0000000000..b5c556019c --- /dev/null +++ b/src/language-service/src/completionHelpers/floors.ts @@ -0,0 +1,69 @@ +import { MarkedString } from "vscode-languageserver-protocol"; +import { + JSONWorkerContribution, + JSONPath, + CompletionsCollector, +} from "vscode-json-languageservice"; +import { IHaConnection } from "../home-assistant/haConnection"; + +export class FloorCompletionContribution implements JSONWorkerContribution { + public static propertyMatches: string[] = ["floor_id", "floor"]; + + constructor(private haConnection: IHaConnection) {} + + public collectDefaultCompletions( + resource: string, + result: CompletionsCollector, + ): Thenable { + return Promise.resolve(null); + } + + public collectPropertyCompletions = async ( + resource: string, + location: JSONPath, + currentWord: string, + addValue: boolean, + isLast: boolean, + result: CompletionsCollector, + ): Promise => { + if (location.length < 2) { + return; + } + const currentNode = location[location.length - 1]; + const parentNode = location[location.length - 2]; // in case or arrays, currentNode is the indexer for the array position + if ( + !FloorCompletionContribution.propertyMatches.some( + (x) => + x === currentNode || + (!Number.isNaN(+currentNode) && x === parentNode), + ) + ) { + return; + } + const floorCompletions = await this.haConnection.getFloorCompletions(); + floorCompletions.forEach((c) => result.add(c)); + }; + + public collectValueCompletions = async ( + resource: string, + location: JSONPath, + currentKey: string, + result: CompletionsCollector, + ): Promise => { + if ( + !FloorCompletionContribution.propertyMatches.some((x) => x === currentKey) + ) { + return; + } + + const floorCompletions = await this.haConnection.getFloorCompletions(); + floorCompletions.forEach((c) => result.add(c)); + }; + + public getInfoContribution( + resource: string, + location: JSONPath, + ): Thenable { + return Promise.resolve([]); + } +} diff --git a/src/language-service/src/completionHelpers/labels.ts b/src/language-service/src/completionHelpers/labels.ts new file mode 100644 index 0000000000..4d4993edb6 --- /dev/null +++ b/src/language-service/src/completionHelpers/labels.ts @@ -0,0 +1,69 @@ +import { MarkedString } from "vscode-languageserver-protocol"; +import { + JSONWorkerContribution, + JSONPath, + CompletionsCollector, +} from "vscode-json-languageservice"; +import { IHaConnection } from "../home-assistant/haConnection"; + +export class LabelCompletionContribution implements JSONWorkerContribution { + public static propertyMatches: string[] = ["label_id", "label"]; + + constructor(private haConnection: IHaConnection) {} + + public collectDefaultCompletions( + resource: string, + result: CompletionsCollector, + ): Thenable { + return Promise.resolve(null); + } + + public collectPropertyCompletions = async ( + resource: string, + location: JSONPath, + currentWord: string, + addValue: boolean, + isLast: boolean, + result: CompletionsCollector, + ): Promise => { + if (location.length < 2) { + return; + } + const currentNode = location[location.length - 1]; + const parentNode = location[location.length - 2]; // in case or arrays, currentNode is the indexer for the array position + if ( + !LabelCompletionContribution.propertyMatches.some( + (x) => + x === currentNode || + (!Number.isNaN(+currentNode) && x === parentNode), + ) + ) { + return; + } + const labelCompletions = await this.haConnection.getLabelCompletions(); + labelCompletions.forEach((c) => result.add(c)); + }; + + public collectValueCompletions = async ( + resource: string, + location: JSONPath, + currentKey: string, + result: CompletionsCollector, + ): Promise => { + if ( + !LabelCompletionContribution.propertyMatches.some((x) => x === currentKey) + ) { + return; + } + + const labelCompletions = await this.haConnection.getLabelCompletions(); + labelCompletions.forEach((c) => result.add(c)); + }; + + public getInfoContribution( + resource: string, + location: JSONPath, + ): Thenable { + return Promise.resolve([]); + } +} diff --git a/src/language-service/src/haLanguageService.ts b/src/language-service/src/haLanguageService.ts index c8bc0243c4..c00517834b 100644 --- a/src/language-service/src/haLanguageService.ts +++ b/src/language-service/src/haLanguageService.ts @@ -19,7 +19,10 @@ import { LanguageSettings, } from "yaml-language-server/out/server/src/languageservice/yamlLanguageService"; import { SchemaServiceForIncludes } from "./schemas/schemaService"; +import { AreaCompletionContribution } from "./completionHelpers/areas"; import { EntityIdCompletionContribution } from "./completionHelpers/entityIds"; +import { FloorCompletionContribution } from "./completionHelpers/floors"; +import { LabelCompletionContribution } from "./completionHelpers/labels"; import { HaConnection } from "./home-assistant/haConnection"; import { ServicesCompletionContribution } from "./completionHelpers/services"; import { DomainCompletionContribution } from "./completionHelpers/domains"; @@ -301,7 +304,10 @@ export class HomeAssistantLanguageService { // we need to add entity_id's to the completion list const properties: { [provider: string]: string[] } = {}; + properties.areas = AreaCompletionContribution.propertyMatches; properties.entities = EntityIdCompletionContribution.propertyMatches; + properties.floors = FloorCompletionContribution.propertyMatches; + properties.labels = LabelCompletionContribution.propertyMatches; properties.services = ServicesCompletionContribution.propertyMatches; properties.domains = DomainCompletionContribution.propertyMatches; @@ -312,6 +318,12 @@ export class HomeAssistantLanguageService { ); let additionalCompletion: CompletionItem[] = []; switch (additionalCompletionProvider) { + case "areas": + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + if (!currentCompletions.items.some((x) => x.data && x.data.isArea)) { + additionalCompletion = await this.haConnection.getAreaCompletions(); + } + break; case "entities": // sometimes the entities are already added, do not add them twice // eslint-disable-next-line @typescript-eslint/no-unsafe-return @@ -326,6 +338,18 @@ export class HomeAssistantLanguageService { additionalCompletion = await this.haConnection.getDomainCompletions(); } break; + case "floors": + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + if (!currentCompletions.items.some((x) => x.data && x.data.isFloor)) { + additionalCompletion = await this.haConnection.getFloorCompletions(); + } + break; + case "labels": + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + if (!currentCompletions.items.some((x) => x.data && x.data.isLabel)) { + additionalCompletion = await this.haConnection.getLabelCompletions(); + } + break; case "services": // eslint-disable-next-line @typescript-eslint/no-unsafe-return if (!currentCompletions.items.some((x) => x.data && x.data.isService)) { diff --git a/src/language-service/src/home-assistant/haConnection.ts b/src/language-service/src/home-assistant/haConnection.ts index 1ff3f51177..5b5f436c6f 100644 --- a/src/language-service/src/home-assistant/haConnection.ts +++ b/src/language-service/src/home-assistant/haConnection.ts @@ -4,15 +4,53 @@ import { MarkupContent, } from "vscode-languageserver-protocol"; import axios, { Method } from "axios"; -import type { - Connection, - HassEntities, - HassServices, - AuthData, +import { + type Connection, + type HassEntities, + type HassServices, + type AuthData, } from "home-assistant-js-websocket"; import { IConfigurationService } from "../configuration"; import { createSocket } from "./socket"; +export type HassArea = { + area_id: string; + floor_id: string | null; + name: string; + picture: string | null; + icon: string | null; + labels: string[]; + aliases: string[]; +}; + +export type HassAreas = { + [area_id: string]: HassArea; +}; + +export type HassFloor = { + floor_id: string; + name: string; + level: number | null; + icon: string | null; + aliases: string[]; +}; + +export type HassFloors = { + [floor_id: string]: HassFloor; +}; + +export type HassLabel = { + label_id: string; + name: string; + icon: string | null; + color: string | null; + description: string | null; +}; + +export type HassLabels = { + [label_id: string]: HassLabel; +}; + // Normal require(), and cast to the static type const ha = // eslint-disable-next-line global-require, @typescript-eslint/no-var-requires @@ -21,16 +59,25 @@ const ha = export interface IHaConnection { tryConnect(): Promise; notifyConfigUpdate(conf: any): Promise; + getAreaCompletions(): Promise; getDomainCompletions(): Promise; getEntityCompletions(): Promise; + getFloorCompletions(): Promise; + getLabelCompletions(): Promise; getServiceCompletions(): Promise; } export class HaConnection implements IHaConnection { private connection: Connection | undefined; + private hassAreas!: Promise; + private hassEntities!: Promise; + private hassFloors!: Promise; + + private hassLabels!: Promise; + private hassServices!: Promise; constructor(private configurationService: IConfigurationService) {} @@ -117,6 +164,127 @@ export class HaConnection implements IHaConnection { } }; + private getHassAreas = async (): Promise => { + if (this.hassAreas !== undefined) { + return this.hassAreas; + } + + await this.createConnection(); + + this.hassAreas = new Promise( + // eslint-disable-next-line @typescript-eslint/require-await, no-async-promise-executor, consistent-return + async (resolve, reject) => { + if (!this.connection) { + return reject(); + } + this.connection + ?.sendMessagePromise({ + type: "config/area_registry/list", + }) + .then((areas) => { + console.log(`Got ${areas.length} areas from Home Assistant`); + const repacked_areas: HassAreas = {}; + areas.forEach((area) => { + repacked_areas[area.area_id] = area; + }); + return resolve(repacked_areas); + }); + }, + ); + return this.hassAreas; + }; + + public async getAreaCompletions(): Promise { + const areas = await this.getHassAreas(); + + if (!areas) { + return []; + } + + const completions: CompletionItem[] = []; + + for (const [, value] of Object.entries(areas)) { + const completionItem = CompletionItem.create(`${value.area_id}`); + completionItem.detail = value.name; + completionItem.kind = CompletionItemKind.Variable; + completionItem.filterText = `${value.area_id} ${value.name}`; + completionItem.insertText = value.area_id; + completionItem.data = {}; + completionItem.data.isArea = true; + + completionItem.documentation = { + kind: "markdown", + value: `**${value.area_id}** \r\n \r\n`, + }; + + let floor = value.floor_id; + if (!floor) { + floor = "No floor assigned"; + } + completionItem.documentation.value += `Floor: ${floor} \r\n \r\n`; + + completions.push(completionItem); + } + return completions; + } + + private getHassFloors = async (): Promise => { + if (this.hassFloors !== undefined) { + return this.hassFloors; + } + + await this.createConnection(); + + this.hassFloors = new Promise( + // eslint-disable-next-line @typescript-eslint/require-await, no-async-promise-executor, consistent-return + async (resolve, reject) => { + if (!this.connection) { + return reject(); + } + this.connection + ?.sendMessagePromise({ + type: "config/floor_registry/list", + }) + .then((floors) => { + console.log(`Got ${floors.length} floors from Home Assistant`); + const repacked_floors: HassFloors = {}; + floors.forEach((floor) => { + repacked_floors[floor.floor_id] = floor; + }); + return resolve(repacked_floors); + }); + }, + ); + return this.hassFloors; + }; + + public async getFloorCompletions(): Promise { + const floors = await this.getHassFloors(); + + if (!floors) { + return []; + } + + const completions: CompletionItem[] = []; + + for (const [, value] of Object.entries(floors)) { + const completionItem = CompletionItem.create(`${value.floor_id}`); + completionItem.detail = value.name; + completionItem.kind = CompletionItemKind.Variable; + completionItem.filterText = `${value.floor_id} ${value.name}`; + completionItem.insertText = value.floor_id; + completionItem.data = {}; + completionItem.data.isFloor = true; + + completionItem.documentation = { + kind: "markdown", + value: `**${value.floor_id}** \r\n`, + }; + completions.push(completionItem); + } + return completions; + } + private getHassEntities = async (): Promise => { if (this.hassEntities !== undefined) { return this.hassEntities; @@ -140,6 +308,63 @@ export class HaConnection implements IHaConnection { return this.hassEntities; }; + private getHassLabels = async (): Promise => { + if (this.hassLabels !== undefined) { + return this.hassLabels; + } + + await this.createConnection(); + + this.hassLabels = new Promise( + // eslint-disable-next-line @typescript-eslint/require-await, no-async-promise-executor, consistent-return + async (resolve, reject) => { + if (!this.connection) { + return reject(); + } + this.connection + ?.sendMessagePromise({ + type: "config/label_registry/list", + }) + .then((labels) => { + console.log(`Got ${labels.length} labels from Home Assistant`); + const repacked_labels: HassLabels = {}; + labels.forEach((label) => { + repacked_labels[label.label_id] = label; + }); + return resolve(repacked_labels); + }); + }, + ); + return this.hassLabels; + }; + + public async getLabelCompletions(): Promise { + const labels = await this.getHassLabels(); + + if (!labels) { + return []; + } + + const completions: CompletionItem[] = []; + + for (const [, value] of Object.entries(labels)) { + const completionItem = CompletionItem.create(`${value.label_id}`); + completionItem.detail = value.name; + completionItem.kind = CompletionItemKind.Variable; + completionItem.filterText = `${value.label_id} ${value.name}`; + completionItem.insertText = value.label_id; + completionItem.data = {}; + completionItem.data.isLabel = true; + + completionItem.documentation = { + kind: "markdown", + value: `**${value.label_id}** \r\n`, + }; + completions.push(completionItem); + } + return completions; + } + public async getEntityCompletions(): Promise { const entities = await this.getHassEntities(); diff --git a/src/language-service/src/schemas/integrations/actions.ts b/src/language-service/src/schemas/integrations/actions.ts index 9a8f11837d..1d79d36019 100644 --- a/src/language-service/src/schemas/integrations/actions.ts +++ b/src/language-service/src/schemas/integrations/actions.ts @@ -5,12 +5,12 @@ import { Area, Data, - Deprecated, Entities, Floor, IncludeList, Integer, Label, + LegacySyntax, SceneEntity, Template, TimePeriod, @@ -182,11 +182,10 @@ export interface EventAction { event_data?: Data; /** - * DEPRECATED as of Home Assistant 0.115. * You can use templates directly in the event_data parameter, replace "event_data_template" with just "event_data". * https://www.home-assistant.io/docs/scripts/#fire-an-event */ - event_data_template?: Deprecated; + event_data_template?: LegacySyntax; } export interface IfAction { @@ -381,10 +380,9 @@ export interface ServiceAction { continue_on_error?: boolean; /** - * The 'service' keyword is being replaced by 'action' keyword - * https://www.home-assistant.io/blog/2024/08/07/release-20248/#goodbye-service-calls-hello-actions- + * Legacy syntax, use "action" instead. */ - service?: Deprecated; + service?: LegacySyntax; /** * The most important action is to call an action. @@ -393,11 +391,10 @@ export interface ServiceAction { action?: string; /** - * DEPRECATED as of Home Assistant 0.115. * You can use templates directly in the service parameter, replace "service_template" with just "service". * https://www.home-assistant.io/docs/scripts/service-calls/#use-templates-to-decide-which-service-to-call */ - service_template?: Deprecated; + service_template?: LegacySyntax; /** * Specify other parameters beside the entity to target. For example, the light turn on service allows specifying the brightness. @@ -406,11 +403,10 @@ export interface ServiceAction { data?: Data | Template; /** - * DEPRECATED as of Home Assistant 0.115. * You can use templates directly in the data parameter, replace "data_template" with just "data". * https://www.home-assistant.io/docs/scripts/service-calls/#use-templates-to-determine-the-attributes */ - data_template?: Deprecated; + data_template?: LegacySyntax; /** * The entity (or entities) to execute this service call on. diff --git a/src/language-service/src/schemas/integrations/selectors.ts b/src/language-service/src/schemas/integrations/selectors.ts index 8bf777f14f..fe3e021e54 100644 --- a/src/language-service/src/schemas/integrations/selectors.ts +++ b/src/language-service/src/schemas/integrations/selectors.ts @@ -7,8 +7,8 @@ import { DeviceClasses, Entity, PositiveInteger, - Deprecated, SupportedFeature, + LegacySyntax, } from "../types"; export type Selector = @@ -207,22 +207,19 @@ export interface DeviceSelector { filter?: DeviceSelectorFilter | DeviceSelectorFilter[]; /** - * DEPRECATED. * You can use filter parameter to filter devices". */ - integration?: Deprecated; + integration?: LegacySyntax; /** - * DEPRECATED. * You can use filter parameter to filter devices". */ - manufacturer?: Deprecated; + manufacturer?: LegacySyntax; /** - * DEPRECATED. * You can use filter parameter to filter devices". */ - model?: Deprecated; + model?: LegacySyntax; /** * Allows selecting multiple devices. If set to `true`, the resulting value of this selector will be a list instead of a single string value. @@ -288,22 +285,19 @@ export interface EntitySelector { include_entities?: Entity[]; /** - * DEPRECATED. * You can use filter parameter to filter entities". */ - integration?: Deprecated; + integration?: LegacySyntax; /** - * DEPRECATED. * You can use filter parameter to filter entities". */ - domain?: Deprecated; + domain?: LegacySyntax; /** - * DEPRECATED. * You can use filter parameter to filter entities". */ - device_class?: Deprecated; + device_class?: LegacySyntax; /** * When filter options are provided, the entities are limited by entities that at least match the given conditions. diff --git a/src/language-service/src/schemas/integrations/triggers.ts b/src/language-service/src/schemas/integrations/triggers.ts index dc698ff4ae..6e52979ca7 100644 --- a/src/language-service/src/schemas/integrations/triggers.ts +++ b/src/language-service/src/schemas/integrations/triggers.ts @@ -18,6 +18,7 @@ import { NumberEntity, SensorEntity, CalendarEntity, + LegacySyntax, } from "../types"; export type Trigger = @@ -74,7 +75,12 @@ interface CalendarTrigger { * Calendar trigger fires when a Calendar event starts or ends. * https://www.home-assistant.io/docs/automation/trigger/#calendar-trigger */ - platform: "calendar"; + trigger?: "calendar"; + + /** + * Legacy syntax, use "trigger: calendar" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -126,7 +132,12 @@ interface ConversationTrigger { * With the sentence trigger, you can match a sentence from a voice assistant. * https://www.home-assistant.io/docs/automation/trigger/#sentence-trigger */ - platform: "conversation"; + trigger?: "conversation"; + + /** + * Legacy syntax, use "trigger: conversation" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -170,7 +181,12 @@ interface DeviceTrigger { * In contrast to state triggers, device triggers are tied to a device and not necessarily an entity. To use a device trigger, set up an automation through the browser frontend. * https://www.home-assistant.io/docs/automation/trigger/#device-triggers */ - platform: "device"; + trigger?: "device"; + + /** + * Legacy syntax, use "trigger: device" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -216,7 +232,12 @@ interface EventTrigger { * Fires when an event is being received. Events are the raw building blocks of Home Assistant. You can match events on just the event name or also require specific event data to be present. * https://www.home-assistant.io/docs/automation/trigger/#event-trigger */ - platform: "event"; + trigger?: "event"; + + /** + * Legacy syntax, use "trigger: event" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -268,7 +289,12 @@ interface GeolocationTrigger { * Geolocation trigger fires when an entity is appearing in or disappearing from a zone. * https://www.home-assistant.io/docs/automation/trigger/#geolocation-trigger */ - platform: "geo_location"; + trigger?: "geo_location"; + + /** + * Legacy syntax, use "trigger: geo_location" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -320,7 +346,12 @@ interface HomeAssistantTrigger { * This trigger fires when Home Assistant has started up or going to shut down. * https://www.home-assistant.io/docs/automation/trigger/#home-assistant-trigger */ - platform: "homeassistant"; + trigger?: "homeassistant"; + + /** + * Legacy syntax, use "trigger: homeassistant" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -360,7 +391,12 @@ interface MqttTrigger { * Fires when a specific message is received on given MQTT topic * https://www.home-assistant.io/docs/automation/trigger/#mqtt-trigger */ - platform: "mqtt"; + trigger?: "mqtt"; + + /** + * Legacy syntax, use "trigger: mqtt" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -429,7 +465,12 @@ interface NumericStateTrigger { * Fires when numeric value of an entity’s state crosses a given threshold. * https://www.home-assistant.io/docs/automation/trigger/#numeric-state-trigger */ - platform: "numeric_state"; + trigger?: "numeric_state"; + + /** + * Legacy syntax, use "trigger: numeric_state" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -499,7 +540,12 @@ interface PersistentNotificationTrigger { * Persistent notification triggers are fired when a persistent_notification is added or removed that matches the configuration options. * https://www.home-assistant.io/docs/automation/trigger/#persistent-notification-trigger */ - platform: "persistent_notification"; + trigger?: "persistent_notification"; + + /** + * Legacy syntax, use "trigger: persistent_notification" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -530,7 +576,12 @@ interface StateTrigger { * This trigger fires when the state of any of given entities changes. * https://www.home-assistant.io/docs/automation/trigger/#state-trigger */ - platform: "state"; + trigger?: "state"; + + /** + * Legacy syntax, use "trigger: state" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -606,7 +657,12 @@ interface SunTrigger { * This trigger fires when the sun is setting or rising. * https://www.home-assistant.io/docs/automation/trigger/#sun-trigger */ - platform: "sun"; + trigger?: "sun"; + + /** + * Legacy syntax, use "trigger: device" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -652,7 +708,12 @@ interface TemplateTrigger { * Template triggers work by evaluating a template on every state change for all of the recognized entities. The trigger will fire if the state change caused the template to render ‘true’. * https://www.home-assistant.io/docs/automation/trigger/#template-trigger */ - platform: "template"; + trigger?: "template"; + + /** + * Legacy syntax, use "trigger: template" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -698,7 +759,12 @@ interface TimeTrigger { * The time trigger is configured to fire once at a specific point in time each day. * https://www.home-assistant.io/docs/automation/trigger/#time-trigger */ - platform: "time"; + trigger?: "time"; + + /** + * Legacy syntax, use "trigger: time" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -741,7 +807,12 @@ interface TimePatternTrigger { * With the time pattern trigger, you can match if the hour, minute or second of the current time matches a specific value. * https://www.home-assistant.io/docs/automation/trigger/#time-pattern-trigger */ - platform: "time_pattern"; + trigger?: "time_pattern"; + + /** + * Legacy syntax, use "trigger: time_pattern" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -796,7 +867,12 @@ interface WebhookTrigger { * Webhook trigger fires when a web request is made to the webhook endpoint. * https://www.home-assistant.io/docs/automation/trigger/#webhook-trigger */ - platform: "webhook"; + trigger?: "webhook"; + + /** + * Legacy syntax, use "trigger: webhook" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -848,7 +924,12 @@ interface ZoneTrigger { * Zone trigger fires when an entity is entering or leaving the zone. For zone automation to work, you need to have setup a device tracker platform that supports reporting GPS coordinates. * https://www.home-assistant.io/docs/automation/trigger/#zone-trigger */ - platform: "zone"; + trigger?: "zone"; + + /** + * Legacy syntax, use "trigger: zone" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. @@ -903,7 +984,12 @@ interface TagTrigger { * This trigger fired when a tag is scanned. * https://www.home-assistant.io/docs/automation/trigger#tag-trigger */ - platform: "tag"; + trigger?: "tag"; + + /** + * Legacy syntax, use "trigger: tag" instead. + */ + platform?: LegacySyntax; /** * Every individual trigger in an automation can be disabled, without removing it. diff --git a/src/language-service/src/schemas/types.ts b/src/language-service/src/schemas/types.ts index b2072f99fb..2d24a1bed8 100644 --- a/src/language-service/src/schemas/types.ts +++ b/src/language-service/src/schemas/types.ts @@ -20,6 +20,12 @@ export type Data = { */ export type Deprecated = any | any[]; +/** + * @TJS-pattern LEGACY_SYNTAX^ + * @items.pattern LEGACY_SYNTAX^ + */ +export type LegacySyntax = any | any[]; + export type DeviceClasses = | DeviceClassesBinarySensor | DeviceClassesCover