Add native token based authentication (#247)

* Replace request with axios for the client side.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Remove 3rd party naming.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Refactor all groupable parameters and add auth header configuration parameter.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Introduce token based authentication via configuration parameter.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Make local LSP also use primary Extension Output Channel.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Add basic auth token check on config change.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Added warn message with authToken config recommendation.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Move Utils into new utils folder. Adapt import paths.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Introduce new config manager class to handle config parameters and logic.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Adapt repo settings for continous watching for file changes.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Move handler for config errors to ConfigManager. Add warning for deprecated config values.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Small improvements for config calls and warning messages.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Fix nested view for items and things TreeViewProvider

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Typo + brackets

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Add basic migration script.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Adapt launch and task config.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Improve migration script. Respect config scopes.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Refactor util classes and types.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Remove migration routine.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Small language client improvements. Add Changelog and major version.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>

* Add missing deprecated parameters back for proper error handling.

Signed-off-by: Jerome Luckenbach <github@luckenba.ch>
pull/253/head
Jerome Luckenbach 2021-03-27 18:42:55 +01:00 committed by GitHub
parent a9a957cc44
commit 8f3f597880
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1346 additions and 359 deletions

2
.vscode/launch.json vendored
View File

@ -14,7 +14,7 @@
"${workspaceRoot}/client/out/**/*.js",
"${workspaceRoot}/serverJS/out/**/*.js"
],
"preLaunchTask": "npm"
"preLaunchTask": "npm: watch"
},
{
"name": "Launch Tests",

17
.vscode/tasks.json vendored
View File

@ -15,7 +15,7 @@
"label": "npm",
"type": "shell",
"command": "npm",
"args": ["run", "compile", "--loglevel", "silent"], //custom script "compile" as defined in package.json
"args": ["run", "watch"], //custom script "watch" as defined in package.json
"presentation": {
"echo": false,
"reveal":"silent",
@ -25,7 +25,20 @@
},
"isBackground": true, // tsc compiler is started in watching mode
"problemMatcher": ["$tsc-watch"]
}
},
{
"type": "npm",
"script": "watch",
"problemMatcher": "$tsc-watch",
"isBackground": true,
"presentation": {
"reveal": "never"
},
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@ -5,6 +5,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- Add native token based authentication (#247)
- Refactor configuration entries (#247)
- Remove 3rd Party references and rename console setting (#247)
- Replace deprecated http library (#247)
## [0.8.2] - 2021-03-19
- Dependency fixes (#239)

608
client/package-lock.json generated
View File

@ -1,9 +1,602 @@
{
"name": "openhab-vscode-extension",
"version": "0.8.0",
"lockfileVersion": 1,
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "openhab-vscode-extension",
"version": "0.8.0",
"license": "SEE LICENSE IN LICENSE",
"dependencies": {
"ascii-table": "0.0.9",
"axios": "^0.21.1",
"copy-paste": "^1.3.0",
"lodash": "^4.17.20",
"request": "^2.88.2",
"request-promise-native": "^1.0.9",
"vscode-languageclient": "6.0.0-next.1"
},
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/vscode": "^1.14.0"
},
"engines": {
"vscode": "^1.37.0"
}
},
"node_modules/@types/axios": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
"integrity": "sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=",
"deprecated": "This is a stub types definition for axios (https://github.com/mzabriskie/axios). axios provides its own type definitions, so you don't need @types/axios installed!",
"dev": true,
"dependencies": {
"axios": "*"
}
},
"node_modules/@types/vscode": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
"integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==",
"dev": true
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"node_modules/ascii-table": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/ascii-table/-/ascii-table-0.0.9.tgz",
"integrity": "sha1-BqZgTWpV1L9BqaR9mHLXp42jHnM="
},
"node_modules/asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
"engines": {
"node": ">=0.8"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"node_modules/aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
"engines": {
"node": "*"
}
},
"node_modules/aws4": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"dependencies": {
"follow-redirects": "^1.10.0"
}
},
"node_modules/bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"dependencies": {
"tweetnacl": "^0.14.3"
}
},
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/copy-paste": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/copy-paste/-/copy-paste-1.3.0.tgz",
"integrity": "sha1-p+bEocKP3t8rCB5yuX3y75X0ce0=",
"dependencies": {
"iconv-lite": "^0.4.8"
},
"optionalDependencies": {
"sync-exec": "~0.6.x"
}
},
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"dependencies": {
"assert-plus": "^1.0.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"dependencies": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"node_modules/extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
"engines": [
"node >=0.6.0"
]
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"node_modules/follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
"engines": {
"node": "*"
}
},
"node_modules/form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"dependencies": {
"assert-plus": "^1.0.0"
}
},
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
"engines": {
"node": ">=4"
}
},
"node_modules/har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"dependencies": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"dependencies": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
},
"engines": {
"node": ">=0.8",
"npm": ">=1.3.7"
}
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"node_modules/jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"node_modules/json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"node_modules/jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"node_modules/lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"node_modules/mime-db": {
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
"integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.28",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
"integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
"dependencies": {
"mime-db": "1.45.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"engines": {
"node": "*"
}
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"node_modules/psl": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
},
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"engines": {
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"dependencies": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"dependencies": {
"lodash": "^4.17.19"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/request-promise-native": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
"dependencies": {
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
},
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
"dependencies": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sync-exec": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz",
"integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=",
"optional": true
},
"node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dependencies": {
"punycode": "^2.1.0"
}
},
"node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"node_modules/vscode-jsonrpc": {
"version": "5.0.0-next.2",
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.2.tgz",
"integrity": "sha512-Q3/jabZUNviCG9hhF6hHWjhrABevPF9mv0aiE2j8BYCAP2k+aHTpjMyk+04MzaAqWYwXdQuZkLSbcYCCqbzJLg==",
"engines": {
"node": ">=8.0.0 || >=10.0.0"
}
},
"node_modules/vscode-languageclient": {
"version": "6.0.0-next.1",
"resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.1.tgz",
"integrity": "sha512-eJ9VjLFNINArgRzLbQ11YlWry7dM93GEODkQBXTRfrSypksiO9qSGr4SHhWgxxP26p4FRSpzc/17+N+Egnnchg==",
"dependencies": {
"semver": "^6.3.0",
"vscode-languageserver-protocol": "^3.15.0-next.9"
},
"engines": {
"vscode": "^1.38.0"
}
},
"node_modules/vscode-languageclient/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/vscode-languageserver-protocol": {
"version": "3.15.0-next.9",
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.9.tgz",
"integrity": "sha512-b9PAxouMmtsLEe8ZjbIMPb7wRWPhckGfgjwZLmp/dWnaAuRPYtY3lGO0/rNbLc3jKIqCVlnEyYVFKalzDAzj0g==",
"dependencies": {
"vscode-jsonrpc": "^5.0.0-next.2",
"vscode-languageserver-types": "^3.15.0-next.5"
}
},
"node_modules/vscode-languageserver-types": {
"version": "3.15.0-next.5",
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.5.tgz",
"integrity": "sha512-7hrELhTeWieUgex3+6692KjCkcmO/+V/bFItM5MHGcBotzwmjEuXjapLLYTYhIspuJ1ibRSik5MhX5YwLpsPiw=="
}
},
"dependencies": {
"@types/axios": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.0.tgz",
"integrity": "sha1-7CMA++fX3d1+udOr+HmZlkyvzkY=",
"dev": true,
"requires": {
"axios": "*"
}
},
"@types/vscode": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
@ -54,6 +647,14 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@ -131,6 +732,11 @@
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"follow-redirects": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz",
"integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA=="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",

View File

@ -18,10 +18,9 @@
},
"dependencies": {
"ascii-table": "0.0.9",
"axios": "^0.21.1",
"copy-paste": "^1.3.0",
"lodash": "^4.17.20",
"request": "^2.88.2",
"request-promise-native": "^1.0.9",
"vscode-languageclient": "6.0.0-next.1"
},
"devDependencies": {

View File

@ -3,8 +3,10 @@ import {
MarkdownString
} from 'vscode'
import * as utils from '../Utils'
import * as request from 'request-promise-native'
import * as utils from '../Utils/Utils'
import axios, { AxiosRequestConfig } from 'axios'
import { ConfigManager } from '../Utils/ConfigManager'
import { OH_CONFIG_PARAMETERS } from '../Utils/types'
/**
* Handles hover actions in editor windows.
@ -92,10 +94,20 @@ export class HoverProvider {
private getRestItemHover(hoveredText: string): Thenable<Hover> {
return new Promise((resolve, reject) => {
console.log(`Requesting => ${utils.getHost()}/rest/items/${hoveredText} <= now`)
let config: AxiosRequestConfig = {
url: utils.getHost() + `/rest/items/${hoveredText}`,
headers: {}
}
request(`${utils.getHost()}/rest/items/${hoveredText}`)
if(ConfigManager.tokenAuthAvailable()){
config.headers = {
'X-OPENHAB-TOKEN': ConfigManager.get(OH_CONFIG_PARAMETERS.connection.authToken)
}
}
axios(config)
.then((response) => {
let result = JSON.parse(response)
let result = response.data
if (!result.error) {
let resultText = new MarkdownString()
@ -146,13 +158,23 @@ export class HoverProvider {
* @returns **true** when update was successful, **false** otherwise
*/
public updateItems() : Boolean {
let config: AxiosRequestConfig = {
url: utils.getHost() + '/rest/items',
headers: {}
}
request(`${utils.getHost()}/rest/items/`)
if(ConfigManager.tokenAuthAvailable()){
config.headers = {
'X-OPENHAB-TOKEN': ConfigManager.get(OH_CONFIG_PARAMETERS.connection.authToken)
}
}
axios(config)
.then((response) => {
// Clear prossible existing array
this.knownItems = new Array<String>()
let result = JSON.parse(response)
let result = response.data
result.forEach(item => {
this.knownItems.push(item.name)

View File

@ -11,6 +11,8 @@ import {
import { Item } from './Item'
import { ItemsModel } from './ItemsModel'
import * as _ from 'lodash'
import { ConfigManager } from '../Utils/ConfigManager'
import { OH_CONFIG_PARAMETERS } from '../Utils/types'
/**
* Produces a list of openHAB items completions
@ -30,9 +32,7 @@ export class ItemsCompletion implements CompletionItemProvider {
public provideCompletionItems(document: TextDocument, position: Position, token: CancellationToken): Thenable<CompletionItem[]> {
return new Promise((resolve, reject) => {
let config = workspace.getConfiguration('openhab')
if (config.useRestApi) {
if (ConfigManager.get(OH_CONFIG_PARAMETERS.useRestApi)) {
this.model.completions.then(completions => {
resolve(completions.map((item: Item) => {
let completionItem = _.assign(new CompletionItem(item.name), {

View File

@ -5,10 +5,12 @@ import {
workspace
} from 'vscode'
import { Item } from './Item'
import * as utils from '../Utils'
import * as utils from '../Utils/Utils'
import * as _ from 'lodash'
import * as request from 'request-promise-native'
import axios, { AxiosRequestConfig } from 'axios'
import { ConfigManager } from '../Utils/ConfigManager'
import { OH_CONFIG_PARAMETERS } from '../Utils/types'
/**
* Collects Items in JSON format from REST API
@ -59,21 +61,26 @@ export class ItemsModel {
* @param transform callback
*/
private sendRequest(uri: string, transform): Thenable<Item[]> {
let options = {
uri: uri || utils.getHost() + '/rest/items',
json: true,
encoding: 'utf8'
let config: AxiosRequestConfig = {
url: uri || utils.getHost() + '/rest/items',
headers: {}
}
if(ConfigManager.tokenAuthAvailable()){
config.headers = {
'X-OPENHAB-TOKEN': ConfigManager.get(OH_CONFIG_PARAMETERS.connection.authToken)
}
}
return new Promise((resolve, _reject) => {
request(options)
.then(function (response: Item[] | Item) {
resolve(transform(response))
}.bind(this))
.catch(err => {
utils.appendToOutput(`Could not reload items for Items Explorer`)
utils.handleRequestError(err).then(err => resolve([]))
})
axios(config)
.then(function (response) {
resolve(transform(response.data as Item[] | Item))
}.bind(this))
.catch(err => {
utils.appendToOutput(`Could not reload items for Items Explorer`)
utils.handleRequestError(err).then(err => resolve([]))
})
})
}

View File

@ -7,7 +7,9 @@ import {
LanguageClient,
LanguageClientOptions,
TransportKind,
ServerOptions
ServerOptions,
ErrorAction,
CloseAction
} from 'vscode-languageclient'
import * as path from 'path'
@ -46,10 +48,16 @@ export class LocalLanguageClientProvider {
configurationSection: "openhab",
fileEvents: workspace.createFileSystemWatcher("**/.clientrc"),
},
// Disable the default error handler
errorHandler: {
error: () => ErrorAction.Continue,
closed: () => CloseAction.DoNotRestart
}
}
// Create the language client and start the client.
const lc = new LanguageClient("openhabLanguageServer", "Openhab Language Server", serverOptions, clientOptions)
return lc.start()
}
}

View File

@ -10,17 +10,21 @@ import {
LanguageClient,
LanguageClientOptions
} from 'vscode-languageclient'
import { ConfigManager } from '../Utils/ConfigManager'
import { OH_CONFIG_PARAMETERS } from '../Utils/types'
import * as utils from '../Utils/Utils'
export class RemoteLanguageClientProvider {
constructor() {
}
public connect(): Disposable {
let config = workspace.getConfiguration('openhab')
let host = config.host.includes('://') ? config.host.split('://')[1] : config.host
let hostConfig = ConfigManager.get(OH_CONFIG_PARAMETERS.connection.host) as string
let host = hostConfig.includes('://') ? hostConfig.split('://')[1] : hostConfig
let connectionInfo = {
host: host,
port: config.remoteLspPort
port: ConfigManager.get(OH_CONFIG_PARAMETERS.languageserver.remotePort) as number
}
let extensions = [
@ -49,7 +53,9 @@ export class RemoteLanguageClientProvider {
synchronize: {
configurationSection: "openhab",
fileEvents: workspace.createFileSystemWatcher("**/.clientrc"),
}
},
outputChannelName: "openHAB Extension",
outputChannel: utils.getOutputChannel()
}
// Create the language client and start the client.

View File

@ -9,7 +9,7 @@ import * as AsciiTable from 'ascii-table'
import { Thing } from './Thing'
import { Channel } from './Channel'
import { humanize } from '../Utils'
import { humanize } from '../Utils/Utils'
/** generate an Item name from a Thing label by using the configured casing */
function generateItemName(label: string) : string {

View File

@ -1,15 +1,11 @@
import {
commands,
Uri,
window,
workspace
} from 'vscode'
import { Thing } from './Thing'
import { Channel } from './Channel'
import * as utils from '../Utils'
import * as utils from '../Utils/Utils'
import * as _ from 'lodash'
import * as request from 'request-promise-native'
import axios, { AxiosRequestConfig } from 'axios'
import { ConfigManager } from '../Utils/ConfigManager'
import { OH_CONFIG_PARAMETERS } from '../Utils/types'
/**
@ -41,21 +37,26 @@ export class ThingsModel {
}
private sendRequest(uri: string, transform): Thenable<Thing[]> {
let options = {
uri: uri || utils.getHost() + '/rest/things',
json: true,
encoding: 'utf8'
let config: AxiosRequestConfig = {
url: uri || utils.getHost() + '/rest/things',
headers: {}
}
if(ConfigManager.tokenAuthAvailable()){
config.headers = {
'X-OPENHAB-TOKEN': ConfigManager.get(OH_CONFIG_PARAMETERS.connection.authToken)
}
}
return new Promise((resolve, reject) => {
request(options)
.then(function (response: Thing[] | Thing) {
resolve(this.sort(transform(response)))
}.bind(this))
.catch(err => {
utils.appendToOutput(`Could not reload items for Things Explorer`)
utils.handleRequestError(err).then(err => resolve([]))
})
axios(config)
.then(function (response) {
resolve(this.sort(transform(response.data as Thing[] | Thing)))
}.bind(this))
.catch(err => {
utils.appendToOutput(`Could not reload items for Things Explorer`)
utils.handleRequestError(err).then(err => resolve([]))
})
})
}

View File

@ -0,0 +1,265 @@
import axios, { AxiosRequestConfig } from 'axios'
import * as vscode from 'vscode'
import { OH_CONFIG_DEPRECATED, OH_CONFIG_PARAMETERS, OH_MESSAGESTRINGS } from './types'
import * as utils from './Utils'
/**
* Handles the extension configuration.
* Provides additional logic for config changes and deprecated parameters.
*
* @author Jerome Luckenbach - Initial contribution
*
*/
export class ConfigManager {
private static instance: ConfigManager|undefined
private currentConfig: vscode.WorkspaceConfiguration
private static ENCODING_MATCH: RegExp = /^(username|password)$/
private deprecationWarningShown: boolean
private static DEPRECATION_WARNING_MESSAGE = `You are using deprecated config values for the openHAB Extension!\n
Those values are still used for the moment, but will be removed in newer extension versions.\n
Please take a look at the current extension settings\nand update to the new config parameters and also remove the deprecated ones.`
/**
* Initialize the ConfigManager
*/
private constructor() {
this.deprecationWarningShown = false
this.updateConfig()
if(this.hasDeprecatedParameters()){
this.showDeprecationWarning()
}
}
/**
* Returns the ConfigManager instance and instanciates it before if not yet available
* @returns {ConfigManager} The ConfigManager instance
*/
private static getInstance(): ConfigManager {
// Create a new instance if there is none available yet
if(!ConfigManager.instance){
ConfigManager.instance = new ConfigManager()
}
return ConfigManager.instance
}
/**
* Fetch and store the latest WorkspaceConfiguration
*/
private updateConfig() {
this.currentConfig = vscode.workspace.getConfiguration('openhab')
console.log("Update Config Manager")
}
/**
* Searches and returns a config value or null
*
* @param configParameter The parameter to search for. Can be used with OH_CONFIG_PARAMETERS constant.
* @returns The config value or null
*/
public static get(configParameter: string): string|number|boolean|null {
let config = ConfigManager.getInstance().currentConfig;
// Check if current parameter is available
if(config.has(configParameter) && config.get(configParameter) !== null){
// Double check if auth token is available and valid
if (configParameter == OH_CONFIG_PARAMETERS.connection.authToken && !ConfigManager.tokenAuthAvailable())
return null
return config.get(configParameter)
}
// If no current Parameter is available, check if a deprecated parameter is available
let parameterObject = configParameter.split('.')
let parameter = parameterObject[parameterObject.length - 1]
let returnValue = null // Return null if nothing is found at all
// Use deprecated version as return value
switch (parameterObject[0]) {
case 'connection':
returnValue = this.checkAndGet(config, parameter)
break
case 'consoleCommand':
returnValue = this.checkAndGet(config, OH_CONFIG_DEPRECATED.consoleCommand)
break
case 'languageserver':
switch (parameter) {
case 'remoteEnabled':
returnValue = this.checkAndGet(config, OH_CONFIG_DEPRECATED.remoteLspEnabled)
break
case 'remotePort':
returnValue = this.checkAndGet(config, OH_CONFIG_DEPRECATED.remoteLspPort)
break
}
break
}
// Output a warning with a "Dismiss" button to prevent warning from showing too often
if(returnValue !== null){
utils.appendToOutput(`Usage of deprecated config ${parameter} detected.`)
}
return returnValue
}
/**
* Checks if ther is an authToken property available and valid
* @returns {boolean} true when tokenAuth is available and useable, false otherwise
*/
public static tokenAuthAvailable(): boolean {
let tokenResult = ConfigManager.getInstance().currentConfig.get(OH_CONFIG_PARAMETERS.connection.authToken, null)
return (!tokenResult || tokenResult === '') ? false : true
}
/**
* Checks if a parameter is available in the given config and if it has a value and returns it.
* Also encodes needed parameters directly
* @param config The workspace configuration to search in
* @param parameter The parameter to search for
* @returns The configuration value, the encoded configuration value when needed or null
*/
private static checkAndGet(config: vscode.WorkspaceConfiguration, parameter: string): string|number|boolean|null {
if(config.has(parameter) && config.get(parameter) !== null){
// Encode basic auth credentials
if(parameter.match(ConfigManager.ENCODING_MATCH))
return encodeURIComponent(config.get(parameter))
return config.get(parameter)
}
return null
}
/**
* Updates an openHAB specific config parameter.
*/
public static update(configParameter: string, value: any, target?: vscode.ConfigurationTarget) {
let config = vscode.workspace.getConfiguration('openhab')
if(config.has(configParameter)) {
if(target == undefined) {
config.update(configParameter, value)
}
else {
config.update(configParameter, value, target)
}
ConfigManager.getInstance().updateConfig()
}
}
/**
* Watches for configuration changes and updates or reacts to openHAB config related changes.
*
* @param context The extension context
*/
public static attachConfigChangeWatcher(context){
let instance = ConfigManager.getInstance()
// Subscribe to all configuration changed events
context.subscriptions.push(vscode.workspace.onDidChangeConfiguration(e => {
if(e.affectsConfiguration('openhab')){
instance.updateConfig()
}
// Check for api token changes and check if a valid apitoken has been set.
// Output an error ortherwise
if(e.affectsConfiguration('openhab.connection.authToken') ){
console.debug(`Auth token config has been changed. Validating token now.`)
const token = instance.currentConfig.get(OH_CONFIG_PARAMETERS.connection.authToken, null)
let config: AxiosRequestConfig = {
url: utils.getHost() + '/rest/auth/apitokens',
headers: {
'X-OPENHAB-TOKEN': `${token}`
}
}
axios(config)
.then((_response) => {
utils.appendToOutput(`Newly configured auth token validated successfully!`)
})
.catch((error) => {
if(error.response.status === 401){
console.error(`Could not validate configured auth token.`, error)
utils.appendToOutput(`Could not validate configured auth token.`)
ConfigManager.getInstance().handleConfigError(error, `Could not validate configured auth token.`)
}
else {
utils.handleRequestError(error)
}
})
}
// Refresh treeviews when a openHAB connection related setting has changed
if(e.affectsConfiguration('openhab.connection') ){
console.debug("openHAB Extension configuration has changed.")
vscode.commands.executeCommand('openhab.command.refreshEntry');
}
}))
}
/**
* Generate an error message and provide some options for solving the error
*
* @param err The current error
* @param message The specific error message
* @param baseMessage The base message available for overwriting the title
*/
private async handleConfigError(err, message: string = OH_MESSAGESTRINGS.moreInfo, baseMessage: string = OH_MESSAGESTRINGS.errors.configValidation) {
// Show error message with action buttons
const showOutput = 'Show Output'
const result = await vscode.window.showErrorMessage(`${baseMessage}\n\n${message}`, showOutput)
// Action based on user input
if(result == showOutput)
utils.getOutputChannel().show()
}
/**
* Check the current config for deprecated and used parameters
* @returns An array of deprecated parameter strings or a boolean
*/
private hasDeprecatedParameters() : string[]|boolean {
let currentConfig = this.currentConfig
let deprecatedParameters : string[] = []
// Append the parameter, if it exists and at least one config value scope has been set manually
for(const parameter in OH_CONFIG_DEPRECATED){
if(currentConfig.has(parameter)){
let inspectresult = currentConfig.inspect(parameter)
if(inspectresult.globalValue != undefined || inspectresult.workspaceValue != undefined){
deprecatedParameters.push(parameter)
}
}
}
return (deprecatedParameters.length != 0) ? deprecatedParameters : false;
}
/**
* Show a warning message, when deprecated config values are used
*/
private async showDeprecationWarning() {
if(!this.deprecationWarningShown){
this.deprecationWarningShown = true
// const migrateStandardValues = 'Migrate minimal config directly!'
// let result = await vscode.window.showWarningMessage(ConfigManager.DEPRECATION_WARNING_MESSAGE, { modal: true }, migrateStandardValues)
vscode.window.showWarningMessage(ConfigManager.DEPRECATION_WARNING_MESSAGE)
// // Action based on user input
// if(result == migrateStandardValues)
// ConfigManager.migrateDeprecatedParameters()
}
}
}

View File

@ -1,189 +1,198 @@
import {
commands,
Uri,
window,
workspace,
} from 'vscode'
import {PreviewPanel} from './WebView/PreviewPanel'
import * as _ from 'lodash'
import * as request from 'request-promise-native'
import { OutputChannel } from 'vscode'
/**
* Create output channel as user display for relevant informations
*/
let extensionOutput: OutputChannel = null
/**
* Humanize function adapter from the previously included underscore.string library
*
* @param str The string to convert
*/
export function humanize(str: string) : string {
return _.upperFirst(
// original 'underscored' of underscore.string
str.trim()
.replace(/([a-z\d])([A-Z]+)/g, '$1_$2')
.replace(/[-\s]+/g, '_')
.toLowerCase()
.replace(/([a-z\d])([A-Z]+)/g, '$1_$2')
.replace(/_id$/, '')
.replace(/_/g, ' ')
// original 'humanize' of underscore.string
.replace(/_id$/, '')
.replace(/_/g, ' ')
.trim()
);
}
/**
* Returns the host of the configured openHAB environment.
* Return value may vary depending on the user configuration (e.g. Authentication settings)
*/
export function getHost() {
let config = workspace.getConfiguration('openhab')
let host = config.host
let port = config.port
let username = encodeURIComponent(config.username)
let password = encodeURIComponent(config.password)
let protocol = 'http'
if (host.includes('://')) {
let split = host.split('://')
host = split[1]
protocol = split[0]
}
let authentication = (username || '') + (password ? ':' + password : '')
authentication += authentication ? '@' : ''
return protocol + '://' + authentication + host + (port === 80 ? '' : ':' + port)
}
/**
* Returns the current simple mode status retreived via rest api
*/
export function getSimpleModeState(): Thenable<Boolean> {
return new Promise((resolve, reject) => {
request(getHost() + '/rest/services/org.eclipse.smarthome.links/config')
.then((response) => {
let responseJson = JSON.parse(response);
resolve(responseJson.autoLinks)
}).catch(() => reject([]))
})
}
/**
* Returns all available sitemaps of the configured openHAB environment via rest api
*/
export function getSitemaps(): Thenable<any[]> {
return new Promise((resolve, reject) => {
request(getHost() + '/rest/sitemaps')
.then((response) => {
resolve(JSON.parse(response))
}).catch(() => reject([]))
})
}
/**
* Opens an external browser with the given url.
*
* @param url The url to navigate to
*/
export function openBrowser(url) {
let editor = window.activeTextEditor
if (!editor) {
window.showInformationMessage('No editor is active')
return
}
let selection = editor.selection
let text = editor.document.getText(selection)
url = url.startsWith('http') ? url : getHost() + url
url = url.replace('%s', text.replace(' ', '%20'))
return commands.executeCommand('vscode.open', Uri.parse(url))
}
/**
* Opens a vscode Webview panel aside, with the given data.
*
* @param extensionPath The path of this extension
* @param query The query to append. Defaults to the basic ui node.
* @param title The title, that will be shown for the UI tab.
*/
export function openUI(extensionPath: string, query: string = "/basicui/app", title?: string) {
let srcPath: string = getHost().concat(query);
appendToOutput(`URL that will be opened is: ${srcPath}`)
PreviewPanel.createOrShow(
extensionPath,
(title !== undefined) ? title : undefined,
srcPath
);
}
/**
* Handle a occuring request error.
*
* @param err The current error
*/
export async function handleRequestError(err) {
let config = workspace.getConfiguration('openhab')
const setHost = 'Set openHAB host'
const disableRest = 'Disable REST API'
const showOutput = 'Show Output'
// Show error message with action buttons
const baseMessage = `Error while connecting to openHAB REST API.`
const message = typeof err.error === 'string' ? err.error : err.error.message
const result = await window.showErrorMessage(`${baseMessage}\nMore information may be found int the openHAB Extension output!`, setHost, disableRest, showOutput)
// Action based on user input
switch (result) {
case setHost:
commands.executeCommand('workbench.action.openWorkspaceSettings')
break
case showOutput:
extensionOutput.show()
break
case disableRest:
config.update('useRestApi', false)
break
default:
break
}
appendToOutput(`---
Error:
${baseMessage}
Message:
${message}
---`)
}
/**
* This will send a message from the extension to its output channel.
* If the channel isn't existing already, it will be created during method run.
*
* @param message The message to append to the extensions output Channel
*/
export function appendToOutput(message: string){
if(!extensionOutput) { extensionOutput = window.createOutputChannel("openHAB Extension") }
extensionOutput.appendLine(message)
}
/**
* Sleep for some time
*
* @param sleepTime wanted time in milliseconds
*/
export async function sleep(sleepTime: number){
return new Promise(resolve => setTimeout(resolve, sleepTime))
import * as vscode from 'vscode'
import { OutputChannel } from 'vscode'
import * as _ from 'lodash'
import axios, { AxiosRequestConfig } from 'axios'
import {PreviewPanel} from '../WebView/PreviewPanel'
import { ConfigManager } from './ConfigManager'
import { OH_CONFIG_PARAMETERS, OH_MESSAGESTRINGS } from './types'
/**
* Create output channel as user display for relevant informations
*/
let extensionOutput: OutputChannel = null
let warningShownAlready: boolean = false
/**
* Humanize function adapter from the previously included underscore.string library
*
* @param str The string to convert
*/
export function humanize(str: string) : string {
return _.upperFirst(
// original 'underscored' of underscore.string
str.trim()
.replace(/([a-z\d])([A-Z]+)/g, '$1_$2')
.replace(/[-\s]+/g, '_')
.toLowerCase()
.replace(/([a-z\d])([A-Z]+)/g, '$1_$2')
.replace(/_id$/, '')
.replace(/_/g, ' ')
// original 'humanize' of underscore.string
.replace(/_id$/, '')
.replace(/_/g, ' ')
.trim()
);
}
/**
* Returns the host of the configured openHAB environment.
* Return value may vary depending on the user configuration (e.g. Authentication settings)
*/
export function getHost() {
let host = ConfigManager.get(OH_CONFIG_PARAMETERS.connection.host) as string
let port = ConfigManager.get(OH_CONFIG_PARAMETERS.connection.port) as number
let protocol = 'http'
if (host.includes('://')) {
let split = host.split('://')
host = split[1]
protocol = split[0]
}
let generatedHost = protocol + '://'
// Prefer token auth over basic auth, if available
if(!ConfigManager.tokenAuthAvailable()){
let username = ConfigManager.get(OH_CONFIG_PARAMETERS.connection.basicAuth.username) as string|null
// Also make sure that there is at least a username given
if(username != null && username != ''){
let password = ConfigManager.get(OH_CONFIG_PARAMETERS.connection.basicAuth.password) as string|null
// Check if given username is a openHAB 3 token
let usernameSegments = username.split('.')
if(usernameSegments.length === 3 && usernameSegments[0] === 'oh'){
const warningString = `Detected openHAB 3 token as username.\nConsider using the recommended **openhab.connection.authToken** config parameter instead.\n\n`
appendToOutput(warningString)
if(!warningShownAlready){
vscode.window.showWarningMessage(warningString)
warningShownAlready = true
}
}
let basicAuth = (username ? username : '') + (password ? ':' + password : '') + '@'
generatedHost += basicAuth
}
}
generatedHost += host + (port === 80 ? '' : ':' + port)
return generatedHost
}
/**
* Returns all available sitemaps of the configured openHAB environment via rest api
*/
export function getSitemaps(): Thenable<any[]> {
return new Promise((resolve, reject) => {
let config: AxiosRequestConfig = {
url: getHost() + '/rest/sitemaps',
headers: {}
}
if(ConfigManager.tokenAuthAvailable()){
config.headers = {
'X-OPENHAB-TOKEN': ConfigManager.get(OH_CONFIG_PARAMETERS.connection.authToken)
}
}
axios(config)
.then((response) => {
resolve(response.data)
}).catch(() => reject([]))
})
}
/**
* Opens an external browser with the given url.
* @param url The url to navigate to
*/
export function openBrowser(url) {
let editor = vscode.window.activeTextEditor
if (!editor) {
vscode.window.showInformationMessage('No editor is active')
return
}
let selection = editor.selection
let text = editor.document.getText(selection)
url = url.startsWith('http') ? url : getHost() + url
url = url.replace('%s', text.replace(' ', '%20'))
return vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(url))
}
/**
* Opens a vscode Webview panel aside, with the given data.
* @param extensionPath The path of this extension
* @param query The query to append. Defaults to the basic ui node.
* @param title The title, that will be shown for the UI tab.
*/
export function openUI(extensionPath: string, query: string = "/basicui/app", title?: string) {
let srcPath: string = getHost().concat(query);
appendToOutput(`URL that will be opened is: ${srcPath}`)
PreviewPanel.createOrShow(
extensionPath,
(title !== undefined) ? title : undefined,
srcPath
);
}
/**
* Handle a occuring request error.
* @param err The current error
*/
export async function handleRequestError(err) {
const disableRest = 'Disable REST API'
const showOutput = 'Show Output'
// Show error message with action buttons
const baseMessage = `Error while connecting to openHAB REST API.`
const message = typeof err.isAxiosError === 'string' ? err.message : err.toString()
const result = await vscode.window.showErrorMessage(`${baseMessage}\n${OH_MESSAGESTRINGS.moreInfo}`, disableRest, showOutput)
// Action based on user input
switch (result) {
case disableRest:
ConfigManager.update(OH_CONFIG_PARAMETERS.useRestApi, false)
break
case showOutput:
extensionOutput.show()
break
}
appendToOutput(`---
Error:
${baseMessage}
Message:
${message}
---`)
}
/**
* This will send a message from the extension to its output channel.
* If the channel isn't existing already, it will be created during method run.
* @param message The message to append to the extensions output Channel
*/
export function appendToOutput(message: string){
getOutputChannel().appendLine(message)
}
/**
* Gets the extensions output channel for referencing
* @returns The extensions output channel
*/
export function getOutputChannel(): OutputChannel {
if(!extensionOutput) { extensionOutput = vscode.window.createOutputChannel("openHAB Extension") }
return extensionOutput
}
/**
* Sleep for some time
* @param sleepTime wanted time in milliseconds
*/
export async function sleep(sleepTime: number){
return new Promise(resolve => setTimeout(resolve, sleepTime))
}

36
client/src/Utils/types.ts Normal file
View File

@ -0,0 +1,36 @@
export const OH_CONFIG_PARAMETERS = {
connection : {
host : 'connection.host',
port : 'connection.port',
authToken : 'connection.authToken',
basicAuth : {
username : 'connection.basicAuth.username',
password : 'connection.basicAuth.password',
}
},
languageserver : {
remoteEnabled : 'languageserver.remoteEnabled',
remotePort : 'languageserver.remotePort',
},
itemCasing : 'itemCasing',
consoleCommand : 'consoleCommand',
useRestApi : 'useRestApi',
}
export const OH_CONFIG_DEPRECATED = {
host : 'host',
port : 'port',
username : 'username',
password : 'password',
remoteLspEnabled : 'remoteLspEnabled',
remoteLspPort : 'remoteLspPort',
consoleCommand : 'karafCommand',
sitemapPreview : 'sitemapPreviewUI',
}
export const OH_MESSAGESTRINGS = {
moreInfo : `More information may be found int the openHAB Extension output!`,
errors : {
configValidation : `Error during config validation`,
},
}

View File

@ -1,6 +1,6 @@
import * as path from 'path'
import * as vscode from 'vscode'
import { appendToOutput } from "../Utils"
import { appendToOutput } from "../Utils/Utils"
/**
* Manages the extension WebView panel
*

View File

@ -1,18 +1,7 @@
'use strict'
import {
commands,
Disposable,
extensions,
ExtensionContext,
languages,
window,
workspace,
StatusBarItem,
StatusBarAlignment
} from 'vscode'
import * as utils from './Utils'
import * as vscode from 'vscode'
import * as utils from './Utils/Utils'
import { ItemsExplorer } from './ItemsExplorer/ItemsExplorer'
import { ThingsExplorer } from './ThingsExplorer/ThingsExplorer'
@ -31,9 +20,11 @@ import * as _ from 'lodash'
import * as ncp from 'copy-paste'
import * as path from 'path'
import * as fs from 'fs'
import axios, { AxiosRequestConfig } from 'axios'
import { ConfigManager } from './Utils/ConfigManager'
let _extensionPath: string
let ohStatusBarItem: StatusBarItem
let ohStatusBarItem: vscode.StatusBarItem
/**
* Initializes the openHAB extension
@ -43,20 +34,15 @@ let ohStatusBarItem: StatusBarItem
* @param config The extension configuration
* @param context The extension context
*/
async function init(disposables: Disposable[], config, context): Promise<void> {
async function init(disposables: vscode.Disposable[], config, context): Promise<void> {
context.subscriptions.push(workspace.onDidChangeConfiguration(e => {
// Handle configuration changes
ConfigManager.attachConfigChangeWatcher(context)
// Refresh treeviews when a connection related setting gets changed
if(e.affectsConfiguration('openhab.host') || e.affectsConfiguration('openhab.password') || e.affectsConfiguration('openhab.port') || e.affectsConfiguration('openhab.username') ){
commands.executeCommand('openhab.command.refreshEntry');
}
}))
disposables.push(commands.registerCommand('openhab.basicUI', () => {
let editor = window.activeTextEditor
disposables.push(vscode.commands.registerCommand('openhab.basicUI', () => {
let editor = vscode.window.activeTextEditor
if (!editor) {
window.showInformationMessage('No editor is active')
vscode.window.showInformationMessage('No editor is active')
return
}
@ -102,19 +88,19 @@ async function init(disposables: Disposable[], config, context): Promise<void> {
}))
disposables.push(commands.registerCommand('openhab.searchCommunity', (phrase?) => {
disposables.push(vscode.commands.registerCommand('openhab.searchCommunity', (phrase?) => {
let query: string = phrase || '%s'
utils.openBrowser(`https://community.openhab.org/search?q=${query}`)
}))
disposables.push(commands.registerCommand('openhab.openConsole', () => {
let command = config.karafCommand.replace(/%openhabhost%/g, config.host)
const terminal = window.createTerminal('openHAB')
disposables.push(vscode.commands.registerCommand('openhab.openConsole', () => {
let command = config.consoleCommand.replace(/%openhabhost%/g, config.connection.host)
const terminal = vscode.window.createTerminal('openHAB')
terminal.sendText(command, true)
terminal.show(false)
}))
disposables.push(commands.registerCommand('openhab.command.things.docs', (query: Thing) =>
disposables.push(vscode.commands.registerCommand('openhab.command.things.docs', (query: Thing) =>
utils.openBrowser(`https://www.openhab.org/addons/bindings/${query.binding}/`)))
if (config.useRestApi) {
@ -123,39 +109,39 @@ async function init(disposables: Disposable[], config, context): Promise<void> {
const itemsCompletion = new ItemsCompletion()
const ohHoverProvider = new HoverProvider()
disposables.push(window.registerTreeDataProvider('openhabItems', itemsExplorer))
disposables.push(window.registerTreeDataProvider('openhabThings', thingsExplorer))
disposables.push(commands.registerCommand('openhab.command.refreshEntry', () => {
disposables.push(vscode.window.registerTreeDataProvider('openhabItems', itemsExplorer))
disposables.push(vscode.window.registerTreeDataProvider('openhabThings', thingsExplorer))
disposables.push(vscode.commands.registerCommand('openhab.command.refreshEntry', () => {
itemsExplorer.refresh()
thingsExplorer.refresh()
}))
disposables.push(commands.registerCommand('openhab.command.copyName', (query) =>
disposables.push(vscode.commands.registerCommand('openhab.command.copyName', (query) =>
ncp.copy(query.name || query.label)))
disposables.push(commands.registerCommand('openhab.command.items.copyState', (query: Item) =>
disposables.push(vscode.commands.registerCommand('openhab.command.items.copyState', (query: Item) =>
ncp.copy(query.state)))
disposables.push(commands.registerCommand('openhab.command.items.addRule', (query: Item) => {
disposables.push(vscode.commands.registerCommand('openhab.command.items.addRule', (query: Item) => {
const ruleProvider = new RuleProvider(query)
ruleProvider.addRule()
}))
disposables.push(commands.registerCommand('openhab.command.items.addToSitemap', (query: Item) => {
disposables.push(vscode.commands.registerCommand('openhab.command.items.addToSitemap', (query: Item) => {
const sitemapProvider = new SitemapPartialProvider(query)
sitemapProvider.addToSitemap()
}))
disposables.push(commands.registerCommand('openhab.command.things.addItems', (query: Thing | Channel) => {
disposables.push(vscode.commands.registerCommand('openhab.command.things.addItems', (query: Thing | Channel) => {
const itemsProvider = new ItemsProvider(query)
itemsProvider.addToItems()
}))
disposables.push(commands.registerCommand('openhab.command.things.copyUID', (query) =>
disposables.push(vscode.commands.registerCommand('openhab.command.things.copyUID', (query) =>
ncp.copy(query.UID || query.uid)))
disposables.push(languages.registerHoverProvider({ language: 'openhab', scheme: 'file'}, {
disposables.push(vscode.languages.registerHoverProvider({ language: 'openhab', scheme: 'file'}, {
provideHover(document, position, token){
@ -181,7 +167,7 @@ async function init(disposables: Disposable[], config, context): Promise<void> {
)
// Listen for document save events, to update the cached items
workspace.onDidSaveTextDocument((savedDocument) => {
vscode.workspace.onDidSaveTextDocument((savedDocument) => {
let fileEnding = savedDocument.fileName.split(".").slice(-1)[0]
if(fileEnding === "items"){
@ -195,7 +181,7 @@ async function init(disposables: Disposable[], config, context): Promise<void> {
})
}
if (config.remoteLspEnabled) {
if (config.languageserver.remoteEnabled) {
const remoteLanguageClientProvider = new RemoteLanguageClientProvider()
disposables.push(remoteLanguageClientProvider.connect())
}
@ -203,18 +189,18 @@ async function init(disposables: Disposable[], config, context): Promise<void> {
const localLanguageClientProvider = new LocalLanguageClientProvider()
disposables.push(localLanguageClientProvider.connect(context))
ohStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, 20)
ohStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 20)
ohStatusBarItem.text = `$(home) openHAB`
ohStatusBarItem.tooltip = `openHAB extension is active currently.`
ohStatusBarItem.show()
}
// This method is called when the extension is activated
export function activate(context: ExtensionContext) {
export function activate(context: vscode.ExtensionContext) {
// Keep the stable extension deactivated, when beta version is installed
let thisExtension = JSON.parse(fs.readFileSync(path.join(context.extensionPath, "package.json"), 'utf8')).name
let betaExtension = extensions.getExtension('openhab.openhab-beta')
let betaExtension = vscode.extensions.getExtension('openhab.openhab-beta')
// When beta is available and we are not beta itself, this extension should not get activated
if(betaExtension !== undefined && thisExtension !== "openhab-beta"){
@ -223,12 +209,12 @@ export function activate(context: ExtensionContext) {
}
// Prepare disposables array, context and config
const disposables: Disposable[] = []
const disposables: vscode.Disposable[] = []
_extensionPath = context.extensionPath
let config = workspace.getConfiguration('openhab')
let config = vscode.workspace.getConfiguration('openhab')
// Spread in the disposables array to the subscription (This will include all disposables from the init method)
context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose()))
context.subscriptions.push(new vscode.Disposable(() => vscode.Disposable.from(...disposables).dispose()))
init(disposables, config, context)
.catch(err => console.error(err))

View File

@ -9,10 +9,10 @@ description: "The openHAB vscode extension provides useful features for configur
You are able to configure the hostname and port for the Sitemap preview.
- `openhab.host` (mandatory), default: openhabianpi
- `openhab.port` (optional), default: 8080
- `openhab.connection.host` (mandatory), default: openhabianpi
- `openhab.connection.port` (optional), default: 8080
*openhab.host* will also work with the IP address of your openHAB instance, instead of the hostname.
*openhab.connection.host* will also work with the IP address of your openHAB instance, instead of the hostname.
These settings should work fine on Windows machines and openHAB installations using the recommended [openHABian](https://www.openhab.org/docs/installation/openhabian.html) setup.
They should be edited if you use macOS or &ast;NIX systems or manual openHAB installations.
@ -25,8 +25,8 @@ For further informations on how to change your settings, visit the official [Vis
```json
{
"openhab.host": "localhost",
"openhab.port": 80
"openhab.connection.host": "localhost",
"openhab.connection.port": 80
}
```
@ -34,8 +34,8 @@ For further informations on how to change your settings, visit the official [Vis
```json
{
"openhab.host": "openhabianpi.local",
"openhab.port": 8080
"openhab.connection.host": "openhabianpi.local",
"openhab.connection.port": 8080
}
```
@ -60,8 +60,8 @@ You may need to reload the VSCode window to take effect.
Since openHAB 3 (with its on default activated api authentication) has been released you have to fulllfil some additional steps to get a working connection.
1. Generate an api token for your user
2. Add the generated token as `openhab.username` configuration
3. Leave `openhab.password` empty
2. Add the generated token as `openhab.connection.basicAuth.username` configuration
3. Leave `openhab.connection.basicAuth.password` empty
4. Reload vscode window
### openHAB REST API and SSL Certificates
@ -119,7 +119,7 @@ In the unlikely case that your language server is running on a port other than t
```json
{
"openhab.remoteLspPort": 5007
"openhab.languageserver.remotePort": 5007
}
```
@ -127,7 +127,7 @@ If you don't want to have your openHAB files validated by Language Server, simpl
```json
{
"openhab.remoteLspEnabled": false
"openhab.languageserver.remoteEnabled": false
}
```
@ -140,11 +140,11 @@ Note that LSP (content assist for rules and syntax validation) won't be exposed,
The following configuration will allow you to access REST API remotely:
```json
"openhab.host": "https://home.myopenhab.org",
"openhab.port": 80,
"openhab.remoteLspEnabled": false,
"openhab.username": "your_myopenhab_email",
"openhab.password": "your_myopenhab_password",
"openhab.connection.host": "https://home.myopenhab.org",
"openhab.connection.port": 80,
"openhab.languageserver.remoteEnabled": false,
"openhab.connection.basicAuth.username": "your_myopenhab_email",
"openhab.connection.basicAuth.password": "your_myopenhab_password",
```
## Sitemap preview with Basic UI
@ -170,10 +170,10 @@ Note that you need to have:
- `ssh` installed on your environment
- Console exposed to the external interface
- `openhab.host` configuration parameter set properly
- `openhab.connection.host` configuration parameter set properly
This feature allows you to modify the new param and e.g. show the openHAB logs immediately:
```bash
"openhab.karafCommand": "ssh openhab@%openhabhost% -p 8101 -t 'log:tail'",
"openhab.consoleCommand": "ssh openhab@%openhabhost% -p 8101 -t 'log:tail'",
```

View File

@ -2,7 +2,7 @@
"name": "openhab",
"displayName": "openHAB",
"description": "Robust tool for openHAB textual configurations. Includes code snippets, syntax highlighting, language server integration and more.",
"version": "0.8.2",
"version": "1.0.0",
"publisher": "openhab",
"icon": "openhab.png",
"repository": {
@ -107,79 +107,105 @@
],
"configuration": {
"type": "object",
"title": "openHAB Configuration",
"title": "openHAB",
"properties": {
"openhab.host": {
"type": [
"string"
],
"default": "openhabianpi",
"description": "Specifies the URL or IP address for the openHAB preview. (Use 'localhost' when developing locally)"
},
"openhab.itemCasing": {
"type": "string",
"default": "camel",
"enum": [
"camel",
"snake"
],
"markdownDescription": "Choose how the `Create Items from Channels` command generates Item names. Use `camel` for `CamelCase` or `snake` for `Upper_Snake_Case`."
"default": "openhabianpi",
"markdownDeprecationMessage": "**Deprecated**: Please use `#openhab.connection.host#` instead."
},
"openhab.karafCommand": {
"type": [
"string"
],
"type": "string",
"default": "ssh openhab@%openhabhost% -p 8101",
"description": "Directly log into openHAB console. Note that this option is available only if you exposed openHAB console."
"markdownDescription": "**Deprecated**: Please use `#openhab.consoleCommand#` instead."
},
"openhab.password": {
"type": [
"string"
],
"type": "string",
"default": "",
"description": "(optional) Specifies the Basic Auth password for accessing the openHAB preview/REST API.\nPlease leave this parameter EMPTY when you are using an api token in openHAB 3!"
"markdownDeprecationMessage": "**Deprecated**: Please use `#openhab.connection.basicAuth.password#` instead."
},
"openhab.port": {
"type": [
"number",
"null"
],
"type": ["number", "null"],
"default": 8080,
"description": "Specifies the port for the openHAB preview."
"markdownDeprecationMessage": "**Deprecated**: Please use `#openhab.connection.port#` instead."
},
"openhab.username": {
"type": "string",
"default": "",
"markdownDeprecationMessage": "**Deprecated**: Please use `#openhab.connection.basicAuth.username#` instead."
},
"openhab.remoteLspEnabled": {
"type": [
"boolean"
],
"type": "boolean",
"default": true,
"description": "Enables communication with Language Server of openHAB instance.\nIf you are facing connection problems make sure to connect your config folder through a dedicated network drive."
"markdownDeprecationMessage": "**Deprecated**: Please use `#openhab.languageserver.remoteLspEnabled#` instead."
},
"openhab.remoteLspPort": {
"type": [
"number",
"null"
],
"type": ["number", "null"],
"default": 5007,
"description": "Specifies the port where openHAB is running its Language Server."
"markdownDeprecationMessage": "**Deprecated**: Please use `#openhab.languageserver.remoteLspPort#` instead."
},
"openhab.sitemapPreviewUI": {
"type": [
"string"
],
"default": "basicui",
"description": "This parameter is deprecated and will be removed with the next major update."
"markdownDeprecationMessage": "**Deprecated**: This parameter is deprecated and will be removed with one of the next updates."
},
"openhab.connection.authToken":{
"type": ["string", "null"],
"default": null,
"markdownDescription": "Specifies the **auth token**, you can generate for your openHAB 3 api access.\n\nSee [Apitoken Documentation](https://openhab.org/docs/configuration/apitokens.html) for further Information!"
},
"openhab.connection.host": {
"type": ["string", "null"],
"default": null,
"markdownDescription": "Specifies the **url** or **IP address** for your openHAB environment.\n\n(Use 'localhost' when developing locally)"
},
"openhab.connection.port": {
"type": ["number", "null"],
"default": null,
"markdownDescription": "Specifies the **port** for your openHAB environment."
},
"openhab.connection.basicAuth.password": {
"type": ["string", "null"],
"default": null,
"markdownDescription": "*OPTIONAL*:\n\nSpecifies the Basic Auth password for accessing the openHAB preview/REST API.\n\nPlease leave this parameter **empty** when you are using an api token in openHAB 3!"
},
"openhab.connection.basicAuth.username": {
"type": ["string", "null"],
"default": null,
"markdownDescription": "*OPTIONAL*:\n\nSpecifies the Basic Auth username for accessing the openHAB preview/REST API."
},
"openhab.languageserver.remoteEnabled": {
"type": "boolean",
"default": true,
"markdownDescription": "Enables communication with Language Server of openHAB instance.\n\nIf you are facing connection problems make sure to connect your config folder through a dedicated network drive."
},
"openhab.languageserver.remotePort": {
"type": ["number", "null"],
"default": 5007,
"markdownDescription": "Specifies the port where openHAB is running its Language Server."
},
"openhab.itemCasing": {
"type": "string",
"default": "camel",
"enum": ["camel", "snake"],
"markdownDescription": "Choose how the `Create Items from Channels` command generates Item names.\n\nUse `camel` for `CamelCase` or `snake` for `Upper_Snake_Case`.",
"markdownEnumDescriptions": [
"Uses the `CamelCase` naming scheme.",
"Uses the `Upper_Snake_Case` naming scheme."
]
},
"openhab.consoleCommand": {
"type": "string",
"default": "ssh openhab@%openhabhost% -p 8101",
"markdownDescription": "Directly log into openHAB console.\n\n**Note** that this option is available only if you exposed openHAB console."
},
"openhab.useRestApi": {
"type": "boolean",
"default": true,
"description": "Connects to openHAB REST API if set to true. If not, Items tree view and things tree view are disabled."
},
"openhab.username": {
"type": [
"string"
],
"default": "",
"description": "(optional) Specifies the Basic Auth username for accessing the openHAB preview/REST API.\nPlease use this parameter for the API TOken too on openHAB 3."
"markdownDescription": "Connects to *openHAB REST API* if set to **true**.\n\nIf not, items tree view and things tree view are **disabled**."
}
}
},
@ -352,14 +378,12 @@
"vscode:prepublish": "npm run webpack",
"watch": "tsc -b -w",
"webpack": "webpack --mode production --config ./client/webpack.config.js && webpack --mode production --config ./serverJS/webpack.config.js",
"webpack-dev": "webpack --mode none --config ./client/webpack.config.js && webpack --mode none --config ./serverJS/webpack.config.js"
"webpack-dev": "webpack --mode development --config ./client/webpack.config.js && webpack --mode development --config ./serverJS/webpack.config.js"
},
"devDependencies": {
"@types/form-data": "^2.2.1",
"@types/lodash": "^4.14.167",
"@types/node": "^8.10.66",
"@types/request": "^2.48.5",
"@types/request-promise-native": "^1.0.15",
"@typescript-eslint/eslint-plugin": "^4.13.0",
"@typescript-eslint/parser": "^4.13.0",
"eslint": "^7.18.0",