Co-authored-by: Alex Weininger <alex.weininger@live.com>
Co-authored-by: Nathan <naturins@microsoft.com>
This commit is contained in:
Alex Weininger 2022-05-13 14:39:39 -07:00 коммит произвёл GitHub
Родитель 8694350c4f
Коммит a991bd57cb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
63 изменённых файлов: 1082 добавлений и 682 удалений

18
.vscode/launch.json поставляемый
Просмотреть файл

@ -19,6 +19,24 @@
"NODE_DEBUG": ""
}
},
{
"name": "Launch Extension + Host",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionDevelopmentPath=${workspaceFolder}/../vscode-azureresourcegroups"
],
"outFiles": [
"${workspaceFolder}/out/**/*.js"
],
"preLaunchTask": "${defaultBuildTask}",
"env": {
"DEBUGTELEMETRY": "v",
"NODE_DEBUG": ""
}
},
{
"name": "Launch Extension (webpack)",
"type": "extensionHost",

205
package-lock.json сгенерированный
Просмотреть файл

@ -1,12 +1,12 @@
{
"name": "vscode-azurefunctions",
"version": "1.6.3-alpha.1",
"version": "1.6.3-alpha.12",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "vscode-azurefunctions",
"version": "1.6.3-alpha.1",
"version": "1.6.3-alpha.12",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"@azure/arm-appinsights": "^4.0.0",
@ -17,9 +17,9 @@
"@azure/arm-storage": "^17.0.0",
"@azure/ms-rest-js": "^2.2.1",
"@azure/storage-blob": "^12.5.0",
"@microsoft/vscode-azext-azureappservice": "^0.1.10",
"@microsoft/vscode-azext-azureutils": "^0.1.3",
"@microsoft/vscode-azext-utils": "^0.1.1",
"@microsoft/vscode-azext-azureappservice": "^0.5.0",
"@microsoft/vscode-azext-azureutils": "^0.2.0",
"@microsoft/vscode-azext-utils": "^0.2.4",
"escape-string-regexp": "^4.0.0",
"extract-zip": "^2.0.1",
"fs-extra": "^4.0.2",
@ -196,6 +196,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@azure/arm-resources-profile-2020-09-01-hybrid/-/arm-resources-profile-2020-09-01-hybrid-1.1.1.tgz",
"integrity": "sha512-6Ku548pHIQULuXzQrxe4zBCxi2g+JBf4bk4HZyYwmyV1ai4ZawDzS8pN/gREhSxeV/t6KtpmHMADi5oxc7wqaA==",
"deprecated": "Please note, versions of this package with version numbers 1.1.1 and below have been deprecated as of 31-March-2022. We strongly encourage you to upgrade to version 2.0.0 or above to continue receiving updates. Refer to our deprecation policy: https://azure.github.io/azure-sdk/policies_support.html for more details.",
"dependencies": {
"@azure/core-auth": "^1.1.4",
"@azure/ms-rest-azure-js": "^2.1.0",
@ -207,6 +208,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@azure/arm-resources-subscriptions/-/arm-resources-subscriptions-1.0.1.tgz",
"integrity": "sha512-aEn2DGAhzGoteEvawnZlP4ATPo2FEyhQHUucDUz7vIaAarPb6CY4T8w+1SJt/SkIN/ZxwvLcFAhv28Tm0mhxXw==",
"deprecated": "Please note, versions of this package with version numbers 1.0.1 and below have been deprecated as of 31-March-2022. We strongly encourage you to upgrade to version 2.0.0 or above to continue receiving updates. Refer to our deprecation policy: https://azure.github.io/azure-sdk/policies_support.html for more details.",
"dependencies": {
"@azure/core-auth": "^1.1.4",
"@azure/ms-rest-azure-js": "^2.1.0",
@ -257,6 +259,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@azure/arm-storage-profile-2020-09-01-hybrid/-/arm-storage-profile-2020-09-01-hybrid-1.1.1.tgz",
"integrity": "sha512-GgsnN8eWctoOvix0vr1RQI/DrBpcR5mIOZ/4FIdJgsIapg6ZWPIYmLYfAyvelfC+KVsEqOGRMTQY5UZ4b9et/A==",
"deprecated": "Please note, versions of this package with version numbers 1.1.1 and below have been deprecated as of 31-March-2022. We strongly encourage you to upgrade to version 2.0.0 or above to continue receiving updates. Refer to our deprecation policy: https://azure.github.io/azure-sdk/policies_support.html for more details.",
"dependencies": {
"@azure/core-auth": "^1.1.4",
"@azure/ms-rest-azure-js": "^2.1.0",
@ -303,14 +306,14 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@azure/core-client": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.4.0.tgz",
"integrity": "sha512-6v1pn4ubNSeI56PUgj2NLR/nfoMfkjYmrtNX0YdXrjxSajKcf/TZc/QJtTFj4wHIvYqU/Yn/g/Zb+MNhFZ5c+Q==",
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.5.0.tgz",
"integrity": "sha512-YNk8i9LT6YcFdFO+RRU0E4Ef+A8Y5lhXo6lz61rwbG8Uo7kSqh0YqK04OexiilM43xd6n3Y9yBhLnb1NFNI9dA==",
"dependencies": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@azure/core-auth": "^1.3.0",
"@azure/core-rest-pipeline": "^1.4.0",
"@azure/core-rest-pipeline": "^1.5.0",
"@azure/core-tracing": "1.0.0-preview.13",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0"
@ -417,9 +420,9 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/@azure/core-rest-pipeline": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.4.0.tgz",
"integrity": "sha512-M2uL9PbvhJIEMRoUad3EnXCHWLN/i0W7D7MQJ9rnIDW7iLVCteUiegdqNa2Cr1/7he/ysEXYiwaXiHmfack/6g==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.8.0.tgz",
"integrity": "sha512-o8eZr96erQpiq8EZhZU/SyN6ncOfZ6bexwN2nMm9WpDmZGvaq907kopADt8XvNhbEF7kRA1l901Pg8mXjWp3UQ==",
"dependencies": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-auth": "^1.3.0",
@ -758,9 +761,9 @@
}
},
"node_modules/@microsoft/vscode-azext-azureappservice": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureappservice/-/vscode-azext-azureappservice-0.1.10.tgz",
"integrity": "sha512-6yCuAP0mOandWnZFrm7UGPU8sBJ25JNGebAotPBPKJnrrYe2LdaDsAJUJTIThoT+EldSPRB0skeZH1xDCRN2gg==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureappservice/-/vscode-azext-azureappservice-0.5.0.tgz",
"integrity": "sha512-8e4G3pXuZYMdUtNKOccinC3ClNo+SlY404Ut6Gbu1HYqif36TeitGwvW7wqqLm8h/8ANrEZdXfd0X9NhI7Ypzg==",
"dependencies": {
"@azure/abort-controller": "^1.0.4",
"@azure/arm-appinsights": "^4.0.0",
@ -771,8 +774,8 @@
"@azure/ms-rest-azure-env": "^2.0.0",
"@azure/ms-rest-js": "^2.3.0",
"@azure/storage-blob": "^12.3.0",
"@microsoft/vscode-azext-azureutils": "^0.1.1",
"@microsoft/vscode-azext-utils": "^0.1.1",
"@microsoft/vscode-azext-azureutils": "^0.2.0",
"@microsoft/vscode-azext-utils": "^0.2.1",
"dayjs": "^1.9.1",
"fs-extra": "^10.0.0",
"glob-gitignore": "^1.0.14",
@ -882,9 +885,9 @@
"integrity": "sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA=="
},
"node_modules/@microsoft/vscode-azext-azureutils": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-0.1.3.tgz",
"integrity": "sha512-Ht5yPiiUDkt4g8ML0Rn5koL8vcOYusD5rX3BS5dO1AIbGDrRIaqZ+i7ietYoZfl8NCj1UszPd67XVUHFGzHYMA==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-0.2.0.tgz",
"integrity": "sha512-QnWxoOcZGT/dEYk7hHSZEzBNN+3fMOLPb/RaabE42/j/EIAExvU09RW7VPjpkQlrNuN72ZajFuWNT3zN1PPWcg==",
"dependencies": {
"@azure/arm-resources": "^5.0.0",
"@azure/arm-resources-profile-2020-09-01-hybrid": "^1.0.0",
@ -892,23 +895,23 @@
"@azure/arm-storage": "^17.0.0",
"@azure/arm-storage-profile-2020-09-01-hybrid": "^1.0.0",
"@azure/ms-rest-js": "^2.2.1",
"@microsoft/vscode-azext-utils": "^0.1.0",
"@microsoft/vscode-azext-utils": "^0.2.0",
"semver": "^5.7.1",
"uuid": "^8.3.2",
"vscode-nls": "^4.1.1"
}
},
"node_modules/@microsoft/vscode-azext-azureutils/node_modules/@azure/arm-resources": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz",
"integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.1.tgz",
"integrity": "sha512-JbZtIqfEulsIA0rC3zM7jfF4KkOnye9aKcaO/jJqxJRm/gM6lAjEv7sL4njW8D+35l50P1f+UuH5OqN+UKJqNA==",
"dependencies": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-auth": "^1.3.0",
"@azure/core-client": "^1.0.0",
"@azure/core-client": "^1.5.0",
"@azure/core-lro": "^2.2.0",
"@azure/core-paging": "^1.2.0",
"@azure/core-rest-pipeline": "^1.1.0",
"@azure/core-rest-pipeline": "^1.8.0",
"tslib": "^2.2.0"
},
"engines": {
@ -1207,9 +1210,9 @@
}
},
"node_modules/@microsoft/vscode-azext-utils": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-0.1.1.tgz",
"integrity": "sha512-5jO8+IPE55HswpzGMbk1+sn5BxKmVfKGw2hs0RAURbgX9MsvnXbOhNwpfqObK0ZCsIi9HWL4N7cBNYFEd1rh9Q==",
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-0.2.4.tgz",
"integrity": "sha512-srD+x3JJWZ5tZDM4A39NsuSayO18zsk86AE8oYqt05VTyvs8gnPit3IiQyXiBK/kBZlrk3vqhVpeTkcf22HoUQ==",
"dependencies": {
"@vscode/extension-telemetry": "^0.4.7",
"dayjs": "^1.9.3",
@ -1820,9 +1823,9 @@
"dev": true
},
"node_modules/@vscode/extension-telemetry": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.4.7.tgz",
"integrity": "sha512-tXjChgxFN6EAfa6LIy/PE3fIbIvj0BnELUmGAG+8tUpsLY3g2iACcVM/UJJXtsU6db29tMqCLITUX2Dd3N06GA==",
"version": "0.4.10",
"resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.4.10.tgz",
"integrity": "sha512-XgyUoWWRQExTmd9DynIIUQo1NPex/zIeetdUAXeBjVuW9ioojM1TcDaSqOa/5QLC7lx+oEXwSU1r0XSBgzyz6w==",
"engines": {
"vscode": "^1.60.0"
}
@ -3667,9 +3670,9 @@
}
},
"node_modules/dayjs": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
"integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig=="
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.1.tgz",
"integrity": "sha512-ER7EjqVAMkRRsxNCC5YqJ9d9VQYuWdGt7aiH2qA5R5wt8ZmWaP2dLUSIK6y/kVzLMlmh1Tvu5xUf4M/wdGJ5KA=="
},
"node_modules/debug": {
"version": "4.3.4",
@ -6752,9 +6755,9 @@
}
},
"node_modules/html-to-text/node_modules/dom-serializer/node_modules/domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
@ -10722,9 +10725,9 @@
}
},
"node_modules/simple-git": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.5.0.tgz",
"integrity": "sha512-fZsaq5nzdxQRhMNs6ESGLpMUHoL5GRP+boWPhq9pMYMKwOGZV2jHOxi8AbFFA2Y/6u4kR99HoULizSbpzaODkA==",
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.7.0.tgz",
"integrity": "sha512-O9HlI83ywqkYqnr7Wh3CqKNNrMkfjzpKQSGtJAhk7+H5P+lAxHBTIPgu/eO/0D9pMciepgs433p0d5S+NYv5Jg==",
"dependencies": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
@ -11495,19 +11498,19 @@
}
},
"node_modules/tas-client": {
"version": "0.1.26",
"resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.26.tgz",
"integrity": "sha512-o9wYpOwf1jhIose0ArEeW/Zr2T/XZnCKDrNXsCiZ/ctpg0DliU76tJ1rbBGlrOvjzLrMY1S3QwZWOAaF7+5HDw==",
"version": "0.1.40",
"resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.40.tgz",
"integrity": "sha512-9kQk4MzB5fsRLn7+qVmFWKKHdYU+pFvcQO4Eh1PyxkWrNeFyIvNvazTAmqxrwQrIcmSgcKVhX/2QAAXFdr0ODw==",
"dependencies": {
"axios": "^0.22.0"
"axios": "^0.26.1"
}
},
"node_modules/tas-client/node_modules/axios": {
"version": "0.22.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.22.0.tgz",
"integrity": "sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w==",
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"dependencies": {
"follow-redirects": "^1.14.4"
"follow-redirects": "^1.14.8"
}
},
"node_modules/terser": {
@ -12756,11 +12759,11 @@
"integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw=="
},
"node_modules/vscode-tas-client": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.27.tgz",
"integrity": "sha512-wyYSdbaSoInXmaXVO54ihvmG6uoRIQ4TdVctJgYqf66oTvUq6e5F3XgtiYRSM6yaqhI0rPqPrYIzLNOO524Z9A==",
"version": "0.1.42",
"resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.42.tgz",
"integrity": "sha512-+8JIJ4HnT/9PXsnZaKIqJEfyvnDslEroVjqRoLVpRS5aXphsx9ZDqCdQdVtPvAsvnGZzmvv6560bVxVJT+3GQA==",
"dependencies": {
"tas-client": "0.1.26"
"tas-client": "0.1.40"
},
"engines": {
"vscode": "^1.19.1"
@ -13685,14 +13688,14 @@
}
},
"@azure/core-client": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.4.0.tgz",
"integrity": "sha512-6v1pn4ubNSeI56PUgj2NLR/nfoMfkjYmrtNX0YdXrjxSajKcf/TZc/QJtTFj4wHIvYqU/Yn/g/Zb+MNhFZ5c+Q==",
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.5.0.tgz",
"integrity": "sha512-YNk8i9LT6YcFdFO+RRU0E4Ef+A8Y5lhXo6lz61rwbG8Uo7kSqh0YqK04OexiilM43xd6n3Y9yBhLnb1NFNI9dA==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@azure/core-auth": "^1.3.0",
"@azure/core-rest-pipeline": "^1.4.0",
"@azure/core-rest-pipeline": "^1.5.0",
"@azure/core-tracing": "1.0.0-preview.13",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0"
@ -13789,9 +13792,9 @@
}
},
"@azure/core-rest-pipeline": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.4.0.tgz",
"integrity": "sha512-M2uL9PbvhJIEMRoUad3EnXCHWLN/i0W7D7MQJ9rnIDW7iLVCteUiegdqNa2Cr1/7he/ysEXYiwaXiHmfack/6g==",
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.8.0.tgz",
"integrity": "sha512-o8eZr96erQpiq8EZhZU/SyN6ncOfZ6bexwN2nMm9WpDmZGvaq907kopADt8XvNhbEF7kRA1l901Pg8mXjWp3UQ==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-auth": "^1.3.0",
@ -14086,9 +14089,9 @@
}
},
"@microsoft/vscode-azext-azureappservice": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureappservice/-/vscode-azext-azureappservice-0.1.10.tgz",
"integrity": "sha512-6yCuAP0mOandWnZFrm7UGPU8sBJ25JNGebAotPBPKJnrrYe2LdaDsAJUJTIThoT+EldSPRB0skeZH1xDCRN2gg==",
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureappservice/-/vscode-azext-azureappservice-0.5.0.tgz",
"integrity": "sha512-8e4G3pXuZYMdUtNKOccinC3ClNo+SlY404Ut6Gbu1HYqif36TeitGwvW7wqqLm8h/8ANrEZdXfd0X9NhI7Ypzg==",
"requires": {
"@azure/abort-controller": "^1.0.4",
"@azure/arm-appinsights": "^4.0.0",
@ -14099,8 +14102,8 @@
"@azure/ms-rest-azure-env": "^2.0.0",
"@azure/ms-rest-js": "^2.3.0",
"@azure/storage-blob": "^12.3.0",
"@microsoft/vscode-azext-azureutils": "^0.1.1",
"@microsoft/vscode-azext-utils": "^0.1.1",
"@microsoft/vscode-azext-azureutils": "^0.2.0",
"@microsoft/vscode-azext-utils": "^0.2.1",
"dayjs": "^1.9.1",
"fs-extra": "^10.0.0",
"glob-gitignore": "^1.0.14",
@ -14192,9 +14195,9 @@
}
},
"@microsoft/vscode-azext-azureutils": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-0.1.3.tgz",
"integrity": "sha512-Ht5yPiiUDkt4g8ML0Rn5koL8vcOYusD5rX3BS5dO1AIbGDrRIaqZ+i7ietYoZfl8NCj1UszPd67XVUHFGzHYMA==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-azureutils/-/vscode-azext-azureutils-0.2.0.tgz",
"integrity": "sha512-QnWxoOcZGT/dEYk7hHSZEzBNN+3fMOLPb/RaabE42/j/EIAExvU09RW7VPjpkQlrNuN72ZajFuWNT3zN1PPWcg==",
"requires": {
"@azure/arm-resources": "^5.0.0",
"@azure/arm-resources-profile-2020-09-01-hybrid": "^1.0.0",
@ -14202,23 +14205,23 @@
"@azure/arm-storage": "^17.0.0",
"@azure/arm-storage-profile-2020-09-01-hybrid": "^1.0.0",
"@azure/ms-rest-js": "^2.2.1",
"@microsoft/vscode-azext-utils": "^0.1.0",
"@microsoft/vscode-azext-utils": "^0.2.0",
"semver": "^5.7.1",
"uuid": "^8.3.2",
"vscode-nls": "^4.1.1"
},
"dependencies": {
"@azure/arm-resources": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.0.tgz",
"integrity": "sha512-eKICohMfZcW0d7tsxS29Z/bznvfUMCu+khJhDJfDlKLqfmqBun6CxBTDeWcNbuckDRxalJ0gZJp5hidC9+Msiw==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-5.0.1.tgz",
"integrity": "sha512-JbZtIqfEulsIA0rC3zM7jfF4KkOnye9aKcaO/jJqxJRm/gM6lAjEv7sL4njW8D+35l50P1f+UuH5OqN+UKJqNA==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"@azure/core-auth": "^1.3.0",
"@azure/core-client": "^1.0.0",
"@azure/core-client": "^1.5.0",
"@azure/core-lro": "^2.2.0",
"@azure/core-paging": "^1.2.0",
"@azure/core-rest-pipeline": "^1.1.0",
"@azure/core-rest-pipeline": "^1.8.0",
"tslib": "^2.2.0"
}
},
@ -14482,9 +14485,9 @@
}
},
"@microsoft/vscode-azext-utils": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-0.1.1.tgz",
"integrity": "sha512-5jO8+IPE55HswpzGMbk1+sn5BxKmVfKGw2hs0RAURbgX9MsvnXbOhNwpfqObK0ZCsIi9HWL4N7cBNYFEd1rh9Q==",
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-0.2.4.tgz",
"integrity": "sha512-srD+x3JJWZ5tZDM4A39NsuSayO18zsk86AE8oYqt05VTyvs8gnPit3IiQyXiBK/kBZlrk3vqhVpeTkcf22HoUQ==",
"requires": {
"@vscode/extension-telemetry": "^0.4.7",
"dayjs": "^1.9.3",
@ -14987,9 +14990,9 @@
"dev": true
},
"@vscode/extension-telemetry": {
"version": "0.4.7",
"resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.4.7.tgz",
"integrity": "sha512-tXjChgxFN6EAfa6LIy/PE3fIbIvj0BnELUmGAG+8tUpsLY3g2iACcVM/UJJXtsU6db29tMqCLITUX2Dd3N06GA=="
"version": "0.4.10",
"resolved": "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.4.10.tgz",
"integrity": "sha512-XgyUoWWRQExTmd9DynIIUQo1NPex/zIeetdUAXeBjVuW9ioojM1TcDaSqOa/5QLC7lx+oEXwSU1r0XSBgzyz6w=="
},
"@webassemblyjs/ast": {
"version": "1.11.1",
@ -16439,9 +16442,9 @@
"dev": true
},
"dayjs": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
"integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig=="
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.1.tgz",
"integrity": "sha512-ER7EjqVAMkRRsxNCC5YqJ9d9VQYuWdGt7aiH2qA5R5wt8ZmWaP2dLUSIK6y/kVzLMlmh1Tvu5xUf4M/wdGJ5KA=="
},
"debug": {
"version": "4.3.4",
@ -18882,9 +18885,9 @@
},
"dependencies": {
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
},
"entities": {
"version": "2.2.0",
@ -21917,9 +21920,9 @@
}
},
"simple-git": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.5.0.tgz",
"integrity": "sha512-fZsaq5nzdxQRhMNs6ESGLpMUHoL5GRP+boWPhq9pMYMKwOGZV2jHOxi8AbFFA2Y/6u4kR99HoULizSbpzaODkA==",
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.7.0.tgz",
"integrity": "sha512-O9HlI83ywqkYqnr7Wh3CqKNNrMkfjzpKQSGtJAhk7+H5P+lAxHBTIPgu/eO/0D9pMciepgs433p0d5S+NYv5Jg==",
"requires": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
@ -22557,19 +22560,19 @@
}
},
"tas-client": {
"version": "0.1.26",
"resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.26.tgz",
"integrity": "sha512-o9wYpOwf1jhIose0ArEeW/Zr2T/XZnCKDrNXsCiZ/ctpg0DliU76tJ1rbBGlrOvjzLrMY1S3QwZWOAaF7+5HDw==",
"version": "0.1.40",
"resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.40.tgz",
"integrity": "sha512-9kQk4MzB5fsRLn7+qVmFWKKHdYU+pFvcQO4Eh1PyxkWrNeFyIvNvazTAmqxrwQrIcmSgcKVhX/2QAAXFdr0ODw==",
"requires": {
"axios": "^0.22.0"
"axios": "^0.26.1"
},
"dependencies": {
"axios": {
"version": "0.22.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.22.0.tgz",
"integrity": "sha512-Z0U3uhqQeg1oNcihswf4ZD57O3NrR1+ZXhxaROaWpDmsDTx7T2HNBV2ulBtie2hwJptu8UvgnJoK+BIqdzh/1w==",
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"requires": {
"follow-redirects": "^1.14.4"
"follow-redirects": "^1.14.8"
}
}
}
@ -23592,11 +23595,11 @@
"integrity": "sha512-7bOHxPsfyuCqmP+hZXscLhiHwe7CSuFE4hyhbs22xPIhQ4jv99FcR4eBzfYYVLP356HNFpdvz63FFb/xw6T4Iw=="
},
"vscode-tas-client": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.27.tgz",
"integrity": "sha512-wyYSdbaSoInXmaXVO54ihvmG6uoRIQ4TdVctJgYqf66oTvUq6e5F3XgtiYRSM6yaqhI0rPqPrYIzLNOO524Z9A==",
"version": "0.1.42",
"resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.42.tgz",
"integrity": "sha512-+8JIJ4HnT/9PXsnZaKIqJEfyvnDslEroVjqRoLVpRS5aXphsx9ZDqCdQdVtPvAsvnGZzmvv6560bVxVJT+3GQA==",
"requires": {
"tas-client": "0.1.26"
"tas-client": "0.1.40"
}
},
"vscode-test": {

Просмотреть файл

@ -2,7 +2,7 @@
"name": "vscode-azurefunctions",
"displayName": "Azure Functions",
"description": "%azureFunctions.description%",
"version": "1.6.3-alpha.1",
"version": "1.6.3-alpha.12",
"publisher": "ms-azuretools",
"icon": "resources/azure-functions.png",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
@ -59,11 +59,9 @@
"onCommand:azureFunctions.executeFunction",
"onCommand:azureFunctions.initProjectForVSCode",
"onCommand:azureFunctions.installOrUpdateFuncCoreTools",
"onCommand:azureFunctions.loadMore",
"onCommand:azureFunctions.openInPortal",
"onCommand:azureFunctions.pickProcess",
"onCommand:azureFunctions.redeploy",
"onCommand:azureFunctions.refresh",
"onCommand:azureFunctions.reportIssue",
"onCommand:azureFunctions.restartFunctionApp",
"onCommand:azureFunctions.setAzureWebJobsStorage",
@ -80,11 +78,29 @@
"onCommand:azureFunctions.viewProperties",
"onDebugInitialConfigurations",
"onUri",
"onView:azFuncTree",
"onView:azureWorkspace",
"workspaceContains:**/host.json"
],
"main": "./main.js",
"contributes": {
"x-azResources": {
"activation": {
"onFetch": [
"microsoft.web/sites"
],
"onResolve": [
"microsoft.web/sites"
]
},
"commands": [
{
"command": "azureFunctions.createFunctionApp",
"title": "%azureFunctions.createFunctionApp%",
"type": "microsoft.web/sites",
"detail": "%azureFunctions.createFunctionAppDetail%"
}
]
},
"commands": [
{
"command": "azureFunctions.addBinding",
@ -168,7 +184,8 @@
{
"command": "azureFunctions.createFunctionApp",
"title": "%azureFunctions.createFunctionApp%",
"category": "Azure Functions"
"category": "Azure Functions",
"icon": "$(add)"
},
{
"command": "azureFunctions.createFunctionAppAdvanced",
@ -245,11 +262,6 @@
"title": "%azureFunctions.installOrUpdateFuncCoreTools%",
"category": "Azure Functions"
},
{
"command": "azureFunctions.loadMore",
"title": "%azureFunctions.loadMore%",
"category": "Azure Functions"
},
{
"command": "azureFunctions.openInPortal",
"title": "%azureFunctions.openInPortal%",
@ -265,12 +277,6 @@
"title": "%azureFunctions.redeploy%",
"category": "Azure Functions"
},
{
"command": "azureFunctions.refresh",
"title": "%azureFunctions.refresh%",
"category": "Azure Functions",
"icon": "$(refresh)"
},
{
"command": "azureFunctions.reportIssue",
"title": "%azureFunctions.reportIssue%",
@ -281,11 +287,6 @@
"title": "%azureFunctions.restartFunctionApp%",
"category": "Azure Functions"
},
{
"command": "azureFunctions.selectSubscriptions",
"title": "Select Subscriptions...",
"icon": "$(filter)"
},
{
"command": "azureFunctions.setAzureWebJobsStorage",
"title": "%azureFunctions.setAzureWebJobsStorage%",
@ -353,297 +354,253 @@
"category": "Azure Functions"
}
],
"views": {
"azure": [
{
"id": "azFuncTree",
"name": "Functions",
"when": "config.azureFunctions.showExplorer == true"
}
]
},
"menus": {
"view/title": [
"azureWorkspaceCreate": [
{
"command": "azureFunctions.createFunction",
"when": "view == azFuncTree",
"group": "navigation@2"
},
{
"command": "azureFunctions.createNewProject",
"when": "view == azFuncTree",
"when": "view == azureWorkspace",
"group": "navigation@1"
},
{
"command": "azureFunctions.deploy",
"when": "view == azFuncTree",
"group": "navigation@3"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree",
"group": "navigation@3"
}
],
"view/item/context": [
{
"command": "azureFunctions.selectSubscriptions",
"when": "view == azFuncTree && viewItem == azureextensionui.azureSubscription",
"group": "inline"
},
{
"command": "azureFunctions.createFunctionApp",
"when": "view == azFuncTree && viewItem == azureextensionui.azureSubscription",
"when": "view == azureResourceGroups && viewItem =~ /azureResourceTypeGroup.*microsoft.web/sites/functionapp/",
"group": "1@1"
},
{
"command": "azureFunctions.createFunctionAppAdvanced",
"when": "view == azFuncTree && viewItem == azureextensionui.azureSubscription",
"when": "view == azureResourceGroups && viewItem =~ /azureResourceTypeGroup.*microsoft.web/sites/functionapp/",
"group": "1@2"
},
{
"command": "azureFunctions.openInPortal",
"when": "view == azFuncTree && viewItem == azureextensionui.azureSubscription",
"group": "2@1"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem == azureextensionui.azureSubscription",
"group": "3@1"
},
{
"command": "azureFunctions.openInPortal",
"when": "view == azFuncTree && viewItem == azFuncProductionSlot",
"group": "1@1"
},
{
"command": "azureFunctions.browseWebsite",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "1@2"
},
{
"command": "azureFunctions.deploy",
"when": "view == azFuncTree && viewItem == azFuncProductionSlot",
"when": "view == azureResourceGroups && viewItem =~ /azFuncProductionSlot/",
"group": "2@1"
},
{
"command": "azureFunctions.deploySlot",
"when": "view == azFuncTree && viewItem == azFuncSlot",
"when": "view == azureResourceGroups && viewItem =~ /azFuncSlot(?!s)/",
"group": "2@1"
},
{
"command": "azureFunctions.configureDeploymentSource",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "2@2"
},
{
"command": "azureFunctions.startFunctionApp",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "3@1"
},
{
"command": "azureFunctions.stopFunctionApp",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "3@2"
},
{
"command": "azureFunctions.restartFunctionApp",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "3@3"
},
{
"command": "azureFunctions.swapSlot",
"when": "view == azFuncTree && viewItem == azFuncSlot",
"when": "view == azureResourceGroups && viewItem =~ /azFuncSlot(?!s)/",
"group": "3@4"
},
{
"command": "azureFunctions.deleteFunctionApp",
"when": "view == azFuncTree && viewItem == azFuncProductionSlot",
"when": "view == azureResourceGroups && viewItem =~ /azFuncProductionSlot/",
"group": "3@5"
},
{
"command": "azureFunctions.deleteSlot",
"when": "view == azFuncTree && viewItem == azFuncSlot",
"when": "view == azureResourceGroups && viewItem =~ /azFuncSlot(?!s)/",
"group": "3@5"
},
{
"command": "azureFunctions.startStreamingLogs",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "4@1"
},
{
"command": "azureFunctions.stopStreamingLogs",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s)/",
"group": "4@2"
},
{
"command": "azureFunctions.startRemoteDebug",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/ && config.azureFunctions.enableRemoteDebugging == true",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot/ && config.azureFunctions.enableRemoteDebugging == true",
"group": "5@1"
},
{
"command": "azureFunctions.startJavaRemoteDebug",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/ && config.azureFunctions.enableJavaRemoteDebugging == true",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot/ && config.azureFunctions.enableJavaRemoteDebugging == true",
"group": "5@2"
},
{
"command": "azureFunctions.viewProperties",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s).*slot/",
"group": "6@1"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem =~ /^azFunc(Production|)Slot$/",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /azFunc(Production|)Slot(?!s).*slot/",
"group": "6@2"
},
{
"command": "azureFunctions.createSlot",
"when": "view == azFuncTree && viewItem == azFuncSlots",
"when": "view == azureResourceGroups && viewItem == azFuncSlots",
"group": "1@1"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem == azFuncSlots",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem == azFuncSlots",
"group": "2@1"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem =~ /Functions;/i",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*Functions;/i",
"group": "1@1"
},
{
"command": "azureFunctions.copyFunctionUrl",
"when": "view == azFuncTree && viewItem =~ /Function;Http;/i",
"when": "view =~ /(azureWorkspace|azureResourceGroups)/ && viewItem =~ /Function;Http;/i",
"group": "1@1"
},
{
"command": "azureFunctions.executeFunction",
"when": "view == azFuncTree && viewItem =~ /Function;/i",
"when": "view =~ /(azureWorkspace|azureResourceGroups)/ && viewItem =~ /Function;/i",
"group": "1@1"
},
{
"command": "azureFunctions.addBinding",
"when": "view == azFuncTree && viewItem =~ /Local;ReadWrite;Function;/i",
"when": "view =~ /(azureWorkspace|azureResourceGroups)/ && viewItem =~ /Local;ReadWrite;Function;/i",
"group": "3@1"
},
{
"command": "azureFunctions.enableFunction",
"when": "view == azFuncTree && viewItem =~ /Function;.*;Disabled;/i",
"when": "view =~ /(azureWorkspace|azureResourceGroups)/ && viewItem =~ /Function;.*;Disabled;/i",
"group": "2@1"
},
{
"command": "azureFunctions.disableFunction",
"when": "view == azFuncTree && viewItem =~ /Function;.*;Enabled;/i",
"when": "view =~ /(azureWorkspace|azureResourceGroups)/ && viewItem =~ /Function;.*;Enabled;/i",
"group": "2@1"
},
{
"command": "azureFunctions.deleteFunction",
"when": "view == azFuncTree && viewItem =~ /Remote;ReadWrite;Function;/i",
"when": "view == azureResourceGroups && viewItem =~ /Remote;ReadWrite;Function;/i",
"group": "2@2"
},
{
"command": "azureFunctions.startStreamingLogs",
"when": "view == azFuncTree && viewItem =~ /Remote;.*;Function;/i",
"when": "view == azureResourceGroups && viewItem =~ /Remote;.*;Function;/i",
"group": "3@1"
},
{
"command": "azureFunctions.stopStreamingLogs",
"when": "view == azFuncTree && viewItem =~ /Remote;.*;Function;/i",
"when": "view == azureResourceGroups && viewItem =~ /Remote;.*;Function;/i",
"group": "3@2"
},
{
"command": "azureFunctions.viewProperties",
"when": "view == azFuncTree && viewItem =~ /Remote;.*;Function;/i",
"when": "view == azureResourceGroups && viewItem =~ /Remote;.*;Function;/i",
"group": "4@1"
},
{
"command": "azureFunctions.appSettings.add",
"when": "view == azFuncTree && viewItem == applicationSettings",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettings.*azFunc/",
"group": "1@1"
},
{
"command": "azureFunctions.appSettings.download",
"when": "view == azFuncTree && viewItem == applicationSettings",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettings.*azFunc/",
"group": "1@2"
},
{
"command": "azureFunctions.appSettings.upload",
"when": "view == azFuncTree && viewItem == applicationSettings",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettings.*azFunc/",
"group": "1@3"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem == applicationSettings",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettings.*azFunc/",
"group": "2@1"
},
{
"command": "azureFunctions.appSettings.edit",
"when": "view == azFuncTree && viewItem == applicationSettingItem",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettingItem.*azFunc/",
"group": "1@1"
},
{
"command": "azureFunctions.appSettings.rename",
"when": "view == azFuncTree && viewItem == applicationSettingItem",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettingItem.*azFunc/",
"group": "1@2"
},
{
"command": "azureFunctions.appSettings.delete",
"when": "view == azFuncTree && viewItem == applicationSettingItem",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettingItem.*azFunc/",
"group": "1@3"
},
{
"command": "azureFunctions.appSettings.toggleSlotSetting",
"when": "view == azFuncTree && viewItem == applicationSettingItem",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettingItem.*azFunc/",
"group": "1@4"
},
{
"command": "azureFunctions.toggleAppSettingVisibility",
"when": "view == azFuncTree && viewItem == applicationSettingItem",
"when": "view == azureResourceGroups && viewItem =~ /applicationSettingItem.*azFunc/",
"group": "inline"
},
{
"command": "azureFunctions.disconnectRepo",
"when": "view == azFuncTree && viewItem == deploymentsConnected",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*deploymentsConnected/",
"group": "1@2"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem =~ /^deployments(C|Unc)onnected$/",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*(deployments(C|Unc)onnected)/",
"group": "2@1"
},
{
"command": "azureFunctions.viewDeploymentLogs",
"when": "view == azFuncTree && viewItem =~ /^deployment//",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*deployment//",
"group": "1@1"
},
{
"command": "azureFunctions.redeploy",
"when": "view == azFuncTree && viewItem =~ /^deployment//",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*deployment//",
"group": "1@2"
},
{
"command": "azureFunctions.openInPortal",
"when": "view == azFuncTree && viewItem =~ /^deployment//",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*deployment//",
"group": "1@3"
},
{
"command": "azureFunctions.viewCommitInGitHub",
"when": "view == azFuncTree && viewItem == deployment/github",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*deployment/github/",
"group": "1@4"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem == siteFiles",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*siteFiles/",
"group": "1@1"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem == logFiles",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*logFiles/",
"group": "1@1"
},
{
"command": "azureFunctions.refresh",
"when": "view == azFuncTree && viewItem == folder",
"command": "azureResourceGroups.refresh",
"when": "view == azureResourceGroups && viewItem =~ /azFunc.*folder/",
"group": "1@1"
}
],
@ -671,21 +628,13 @@
],
"commandPalette": [
{
"command": "azureFunctions.loadMore",
"command": "azureFunctions.openInPortal",
"when": "never"
},
{
"command": "azureFunctions.pickProcess",
"when": "never"
},
{
"command": "azureFunctions.refresh",
"when": "never"
},
{
"command": "azureFunctions.selectSubscriptions",
"when": "never"
},
{
"command": "azureFunctions.startJavaRemoteDebug",
"when": "config.azureFunctions.enableJavaRemoteDebugging == true"
@ -697,6 +646,10 @@
{
"command": "azureFunctions.toggleAppSettingVisibility",
"when": "never"
},
{
"command": "azureFunctions.viewProperties",
"when": "never"
}
],
"editor/context": [
@ -1118,9 +1071,9 @@
"@azure/arm-storage": "^17.0.0",
"@azure/ms-rest-js": "^2.2.1",
"@azure/storage-blob": "^12.5.0",
"@microsoft/vscode-azext-azureappservice": "^0.1.10",
"@microsoft/vscode-azext-azureutils": "^0.1.3",
"@microsoft/vscode-azext-utils": "^0.1.1",
"@microsoft/vscode-azext-azureappservice": "^0.5.0",
"@microsoft/vscode-azext-azureutils": "^0.2.0",
"@microsoft/vscode-azext-utils": "^0.2.4",
"escape-string-regexp": "^4.0.0",
"extract-zip": "^2.0.1",
"fs-extra": "^4.0.2",

Просмотреть файл

@ -16,6 +16,7 @@
"azureFunctions.createFunction": "Create Function...",
"azureFunctions.createFunctionApp": "Create Function App in Azure...",
"azureFunctions.createFunctionAppAdvanced": "Create Function App in Azure... (Advanced)",
"azureFunctions.createFunctionAppDetail": "For serverless, event driven apps and automation.",
"azureFunctions.createNewProject": "Create New Project...",
"azureFunctions.createPythonVenv": "Create a virtual environment when creating a new Python project.",
"azureFunctions.createSlot": "Create Slot...",
@ -37,7 +38,6 @@
"azureFunctions.initProjectForVSCode": "Initialize Project for Use with VS Code...",
"azureFunctions.installOrUpdateFuncCoreTools": "Install or Update Azure Functions Core Tools",
"azureFunctions.javaBuildTool": "Build tool for Java Functions project",
"azureFunctions.loadMore": "Load More",
"azureFunctions.openInPortal": "Open in Portal",
"azureFunctions.pickProcess": "Pick Process",
"azureFunctions.pickProcessTimeout": "The timeout (in seconds) to be used when searching for the Azure Functions host process. Since a build is required every time you F5, you may need to adjust this based on how long your build takes.",
@ -61,7 +61,6 @@
"azureFunctions.projectTemplateKey": "A key used to identify which templates to use for this project. In most cases, this will be automatically detected and should not need to be set.",
"azureFunctions.pythonVenv": "The name of the Python virtual environment used for your project. A virtual environment is required to debug and deploy Python functions.",
"azureFunctions.redeploy": "Redeploy",
"azureFunctions.refresh": "Refresh",
"azureFunctions.reportIssue": "Report Issue...",
"azureFunctions.requestTimeout": "The timeout (in seconds) to be used when making requests, for example getting the latest templates.",
"azureFunctions.restartFunctionApp": "Restart",

Просмотреть файл

@ -0,0 +1,25 @@
import { callWithTelemetryAndErrorHandling, IActionContext, ISubscriptionContext, nonNullProp } from "@microsoft/vscode-azext-utils";
import { AppResource, AppResourceResolver } from "@microsoft/vscode-azext-utils/hostapi";
import { ResolvedFunctionAppResource } from "./tree/ResolvedFunctionAppResource";
import { getResourceGroupFromId } from "./utils/azure";
import { createWebSiteClient } from "./utils/azureClients";
export class FunctionAppResolver implements AppResourceResolver {
public async resolveResource(subContext: ISubscriptionContext, resource: AppResource): Promise<ResolvedFunctionAppResource | null> {
return await callWithTelemetryAndErrorHandling('resolveResource', async (context: IActionContext) => {
try {
const client = await createWebSiteClient({ ...context, ...subContext });
const site = await client.webApps.get(getResourceGroupFromId(nonNullProp(resource, 'id')), nonNullProp(resource, 'name'));
return new ResolvedFunctionAppResource(subContext, site);
} catch (e) {
console.error({ ...context, ...subContext });
throw e;
}
}) ?? null;
}
public matchesResource(resource: AppResource): boolean {
return resource.type.toLowerCase() === 'microsoft.web/sites' && !!resource.kind?.includes('functionapp');
}
}

Просмотреть файл

@ -0,0 +1,97 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AzExtParentTreeItem, AzExtTreeItem, callWithTelemetryAndErrorHandling, IActionContext } from "@microsoft/vscode-azext-utils";
import { WorkspaceResourceProvider } from "@microsoft/vscode-azext-utils/hostapi";
import * as path from 'path';
import { Disposable, workspace, WorkspaceFolder } from "vscode";
import { tryGetFunctionProjectRoot } from "./commands/createNewProject/verifyIsProject";
import { getFunctionAppName, getJavaDebugSubpath } from "./commands/initProjectForVSCode/InitVSCodeStep/JavaInitVSCodeStep";
import { funcVersionSetting, JavaBuildTool, javaBuildTool, ProjectLanguage, projectLanguageSetting } from "./constants";
import { FuncVersion, tryParseFuncVersion } from "./FuncVersion";
import { localize } from "./localize";
import { InitLocalProjectTreeItem } from "./tree/localProject/InitLocalProjectTreeItem";
import { InvalidLocalProjectTreeItem } from "./tree/localProject/InvalidLocalProjectTreeItem";
import { LocalProjectTreeItem } from "./tree/localProject/LocalProjectTreeItem";
import { dotnetUtils } from "./utils/dotnetUtils";
import { getWorkspaceSetting } from "./vsCodeConfig/settings";
export class FunctionsLocalResourceProvider implements WorkspaceResourceProvider {
public disposables: Disposable[] = [];
public async provideResources(parent: AzExtParentTreeItem): Promise<AzExtTreeItem[] | null | undefined> {
return await callWithTelemetryAndErrorHandling('AzureAccountTreeItemWithProjects.provideResources', async (context: IActionContext) => {
const children: AzExtTreeItem[] = [];
Disposable.from(...this._projectDisposables).dispose();
this._projectDisposables = [];
const folders: readonly WorkspaceFolder[] = workspace.workspaceFolders || [];
for (const folder of folders) {
const projectPath: string | undefined = await tryGetFunctionProjectRoot(context, folder);
if (projectPath) {
try {
const language: ProjectLanguage | undefined = getWorkspaceSetting(projectLanguageSetting, projectPath);
const version: FuncVersion | undefined = tryParseFuncVersion(getWorkspaceSetting(funcVersionSetting, projectPath));
if (language === undefined || version === undefined) {
children.push(new InitLocalProjectTreeItem(parent, projectPath, folder));
} else {
let preCompiledProjectPath: string | undefined;
let effectiveProjectPath: string;
let isIsolated: boolean | undefined;
const compiledProjectInfo: CompiledProjectInfo | undefined = await getCompiledProjectInfo(context, projectPath, language);
if (compiledProjectInfo) {
preCompiledProjectPath = projectPath;
effectiveProjectPath = compiledProjectInfo.compiledProjectPath;
isIsolated = compiledProjectInfo.isIsolated;
} else {
effectiveProjectPath = projectPath;
}
const treeItem: LocalProjectTreeItem = new LocalProjectTreeItem(parent, { effectiveProjectPath, folder, language, version, preCompiledProjectPath, isIsolated });
this._projectDisposables.push(treeItem);
children.push(treeItem);
}
} catch (error) {
children.push(new InvalidLocalProjectTreeItem(parent, projectPath, error, folder));
}
}
}
return children;
});
}
private _projectDisposables: Disposable[] = [];
public dispose(): void {
Disposable.from(...this._projectDisposables).dispose();
}
}
type CompiledProjectInfo = { compiledProjectPath: string; isIsolated: boolean };
async function getCompiledProjectInfo(context: IActionContext, projectPath: string, projectLanguage: ProjectLanguage): Promise<CompiledProjectInfo | undefined> {
if (projectLanguage === ProjectLanguage.CSharp || projectLanguage === ProjectLanguage.FSharp) {
const projFiles: dotnetUtils.ProjectFile[] = await dotnetUtils.getProjFiles(context, projectLanguage, projectPath);
if (projFiles.length === 1) {
const targetFramework: string = await dotnetUtils.getTargetFramework(projFiles[0]);
const isIsolated = await dotnetUtils.getIsIsolated(projFiles[0]);
return { compiledProjectPath: path.join(projectPath, dotnetUtils.getDotnetDebugSubpath(targetFramework)), isIsolated };
} else {
throw new Error(localize('unableToFindProj', 'Unable to detect project file.'));
}
} else if (projectLanguage === ProjectLanguage.Java) {
const buildTool: JavaBuildTool | undefined = getWorkspaceSetting(javaBuildTool, projectPath);
const functionAppName: string | undefined = await getFunctionAppName(projectPath, buildTool);
if (!functionAppName) {
throw new Error(localize('unableToGetFunctionAppName', 'Unable to detect property "functionAppName" in pom.xml.'));
} else {
return { compiledProjectPath: path.join(projectPath, getJavaDebugSubpath(functionAppName, buildTool)), isIsolated: false };
}
} else {
return undefined;
}
}

Просмотреть файл

@ -36,7 +36,7 @@ export async function addBinding(context: IActionContext, data: Uri | LocalFunct
} else {
if (!data) {
const noItemFoundErrorMessage: string = localize('noLocalProject', 'No matching functions found. C# and Java projects do not support this operation.');
data = await ext.tree.showTreeItemPicker<LocalFunctionTreeItem>(/Local;ReadWrite;Function;/i, { ...context, noItemFoundErrorMessage });
data = await ext.rgApi.workspaceResourceTree.showTreeItemPicker<LocalFunctionTreeItem>(/Local;ReadWrite;Function;/i, { ...context, noItemFoundErrorMessage });
}
if (!data.functionJsonPath) {

Просмотреть файл

@ -8,9 +8,9 @@ import { ext } from "../../extensionVariables";
export async function revealTreeItem(resourceId: string): Promise<void> {
return await callWithTelemetryAndErrorHandling('api.revealTreeItem', async (context: IActionContext) => {
const node: AzExtTreeItem | undefined = await ext.tree.findTreeItem(resourceId, { ...context, loadAll: true });
const node: AzExtTreeItem | undefined = await ext.rgApi.tree.findTreeItem(resourceId, { ...context, loadAll: true });
if (node) {
await ext.treeView.reveal(node, { select: true, focus: true, expand: true });
await ext.rgApi.treeView.reveal(node, { select: true, focus: true, expand: true });
}
});
}

Просмотреть файл

@ -8,7 +8,7 @@ import { AppSettingsTreeItem, confirmOverwriteSettings, IAppSettingsClient } fro
import { IActionContext } from "@microsoft/vscode-azext-utils";
import * as fse from 'fs-extra';
import * as vscode from 'vscode';
import { localSettingsFileName, viewOutput } from "../../constants";
import { functionFilter, localSettingsFileName, viewOutput } from "../../constants";
import { ext } from "../../extensionVariables";
import { getLocalSettingsJson, ILocalSettingsJson } from "../../funcConfig/local.settings";
import { localize } from "../../localize";
@ -19,7 +19,10 @@ import { getLocalSettingsFile } from "./getLocalSettingsFile";
export async function downloadAppSettings(context: IActionContext, node?: AppSettingsTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<AppSettingsTreeItem>(AppSettingsTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<AppSettingsTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(AppSettingsTreeItem.contextValue)
});
}
const client: IAppSettingsClient = await node.clientProvider.createClient(context);

Просмотреть файл

@ -5,11 +5,15 @@
import { AppSettingTreeItem } from "@microsoft/vscode-azext-azureappservice";
import { IActionContext } from "@microsoft/vscode-azext-utils";
import { functionFilter } from "../../constants";
import { ext } from "../../extensionVariables";
export async function toggleSlotSetting(context: IActionContext, node?: AppSettingTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<AppSettingTreeItem>(AppSettingTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<AppSettingTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(AppSettingTreeItem.contextValue)
});
}
await node.toggleSlotSetting(context);

Просмотреть файл

@ -8,7 +8,7 @@ import { AppSettingsTreeItem, confirmOverwriteSettings, IAppSettingsClient } fro
import { IActionContext } from "@microsoft/vscode-azext-utils";
import * as fse from 'fs-extra';
import * as vscode from 'vscode';
import { localSettingsFileName, viewOutput } from "../../constants";
import { functionFilter, localSettingsFileName, viewOutput } from "../../constants";
import { ext } from "../../extensionVariables";
import { ILocalSettingsJson } from "../../funcConfig/local.settings";
import { localize } from "../../localize";
@ -20,7 +20,10 @@ import { getLocalSettingsFile } from "./getLocalSettingsFile";
export async function uploadAppSettings(context: IActionContext, node?: AppSettingsTreeItem, workspaceFolder?: vscode.WorkspaceFolder, exclude?: (RegExp | string)[]): Promise<void> {
context.telemetry.eventVersion = 2;
if (!node) {
node = await ext.tree.showTreeItemPicker<AppSettingsTreeItem>(AppSettingsTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<AppSettingsTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(AppSettingsTreeItem.contextValue)
});
}
const client: IAppSettingsClient = await node.clientProvider.createClient(context);

Просмотреть файл

@ -4,14 +4,16 @@
*--------------------------------------------------------------------------------------------*/
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
import { SlotTreeItem } from '../tree/SlotTreeItem';
import { openUrl } from '../utils/openUrl';
export async function browseWebsite(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function browseWebsite(context: IActionContext, node?: SlotTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
});
}
await openUrl(node.site.defaultHostUrl);

Просмотреть файл

@ -5,13 +5,17 @@
import { editScmType } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../tree/SlotTreeItem';
export async function configureDeploymentSource(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function configureDeploymentSource(context: IActionContext, node?: SlotTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const updatedScmType: string | undefined = await editScmType(context, node.site, node.subscription);

Просмотреть файл

@ -5,6 +5,7 @@
import { IActionContext } from '@microsoft/vscode-azext-utils';
import * as vscode from 'vscode';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { localize } from '../localize';
import { FunctionTreeItemBase } from '../tree/FunctionTreeItemBase';
@ -12,7 +13,10 @@ import { FunctionTreeItemBase } from '../tree/FunctionTreeItemBase';
export async function copyFunctionUrl(context: IActionContext, node?: FunctionTreeItemBase): Promise<void> {
if (!node) {
const noItemFoundErrorMessage: string = localize('noHTTPFunctions', 'No HTTP functions found.');
node = await ext.tree.showTreeItemPicker<FunctionTreeItemBase>(/Function;Http;/i, { ...context, noItemFoundErrorMessage });
node = await ext.rgApi.pickAppResource<FunctionTreeItemBase>({ ...context, noItemFoundErrorMessage }, {
filter: functionFilter,
expectedChildContextValue: /Function;Http;/i
});
}
const triggerRequest = await node.getTriggerRequest(context);

Просмотреть файл

@ -4,11 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import { AzExtParentTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
export async function createChildNode(context: IActionContext, expectedContextValue: string | RegExp, node?: AzExtParentTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<AzExtParentTreeItem>(expectedContextValue, context);
node = await ext.rgApi.pickAppResource<AzExtParentTreeItem>({ ...context, suppressCreatePick: true }, {
filter: functionFilter,
expectedChildContextValue: expectedContextValue
});
}
await node.createChild(context);

Просмотреть файл

@ -10,6 +10,7 @@ import { NoWorkspaceError } from '../../errors';
import { addLocalFuncTelemetry } from '../../funcCoreTools/getLocalFuncCoreToolsVersion';
import { FuncVersion } from '../../FuncVersion';
import { localize } from '../../localize';
import { LocalProjectTreeItem } from '../../tree/localProject/LocalProjectTreeItem';
import { getContainingWorkspace } from '../../utils/workspace';
import * as api from '../../vscode-azurefunctions.api';
import { getWorkspaceSetting } from '../../vsCodeConfig/settings';
@ -24,13 +25,17 @@ import { IFunctionWizardContext } from './IFunctionWizardContext';
*/
export async function createFunctionFromCommand(
context: IActionContext,
folderPath?: string,
folderPath?: string | LocalProjectTreeItem,
templateId?: string,
functionName?: string,
functionSettings?: { [key: string]: string | undefined },
language?: ProjectLanguage,
version?: FuncVersion): Promise<void> {
if (folderPath && typeof folderPath !== 'string') {
folderPath = undefined;
}
await createFunctionInternal(context, {
folderPath,
templateId,

Просмотреть файл

@ -7,6 +7,7 @@ import { NameValuePair, Site, SiteConfig, WebSiteManagementClient } from '@azure
import { CustomLocation, IAppServiceWizardContext, ParsedSite, WebsiteOS } from '@microsoft/vscode-azext-azureappservice';
import { LocationListStep } from '@microsoft/vscode-azext-azureutils';
import { AzureWizardExecuteStep, parseError } from '@microsoft/vscode-azext-utils';
import { AppResource } from '@microsoft/vscode-azext-utils/hostapi';
import { Progress } from 'vscode';
import { contentConnectionStringKey, contentShareKey, extensionVersionKey, ProjectLanguage, runFromPackageKey, webProvider } from '../../constants';
import { ext } from '../../extensionVariables';
@ -44,6 +45,7 @@ export class FunctionAppCreateStep extends AzureWizardExecuteStep<IFunctionAppWi
const client: WebSiteManagementClient = await createWebSiteClient(context);
context.site = await client.webApps.beginCreateOrUpdateAndWait(rgName, siteName, await this.getNewSite(context, stack));
context.activityResult = context.site as AppResource;
const site = new ParsedSite(context.site, context);
if (!site.isLinux) { // not supported on linux

Просмотреть файл

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IAppServiceWizardContext } from '@microsoft/vscode-azext-azureappservice';
import { ICreateChildImplContext } from '@microsoft/vscode-azext-utils';
import { ExecuteActivityContext, ICreateChildImplContext } from '@microsoft/vscode-azext-utils';
import { FuncVersion } from '../../FuncVersion';
import { AppStackMajorVersion, AppStackMinorVersion } from './stacks/models/AppStackModel';
import { FunctionAppRuntimes, FunctionAppStack } from './stacks/models/FunctionAppStackModel';
@ -15,7 +15,7 @@ export type FullFunctionAppStack = {
minorVersion: AppStackMinorVersion<FunctionAppRuntimes>;
};
export interface IFunctionAppWizardContext extends IAppServiceWizardContext, ICreateChildImplContext {
export interface IFunctionAppWizardContext extends IAppServiceWizardContext, ICreateChildImplContext, ExecuteActivityContext {
version: FuncVersion;
language: string | undefined;
stackFilter?: string;

Просмотреть файл

@ -6,26 +6,28 @@
import { AzExtParentTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { ext } from '../../extensionVariables';
import { localize } from '../../localize';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { SlotTreeItem } from '../../tree/SlotTreeItem';
import { ICreateFunctionAppContext, SubscriptionTreeItem } from '../../tree/SubscriptionTreeItem';
import { ISiteCreatedOptions } from './showSiteCreated';
export async function createFunctionApp(context: IActionContext & Partial<ICreateFunctionAppContext>, subscription?: AzExtParentTreeItem | string, newResourceGroupName?: string): Promise<string> {
let node: AzExtParentTreeItem | undefined;
if (typeof subscription === 'string') {
node = await ext.tree.findTreeItem(`/subscriptions/${subscription}`, context);
node = await ext.rgApi.tree.findTreeItem(`/subscriptions/${subscription}`, context);
if (!node) {
throw new Error(localize('noMatchingSubscription', 'Failed to find a subscription matching id "{0}".', subscription));
}
} else if (!subscription) {
node = await ext.tree.showTreeItemPicker<AzExtParentTreeItem>(SubscriptionTreeItem.contextValue, context);
node = await ext.rgApi.tree.showTreeItemPicker<AzExtParentTreeItem>(SubscriptionTreeItem.contextValue, context);
} else {
node = subscription;
}
context.newResourceGroupName = newResourceGroupName;
(<ISiteCreatedOptions>context).showCreatedNotification = true;
const funcAppNode: ProductionSlotTreeItem = await node.createChild(context);
const funcAppNode: SlotTreeItem = await SubscriptionTreeItem.createChild(context as ICreateFunctionAppContext, node as SubscriptionTreeItem);
return funcAppNode.fullId;
}

Просмотреть файл

@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { SlotsTreeItem } from '../tree/SlotsTreeItem';
import { SlotTreeItem } from '../tree/SlotTreeItem';
@ -11,7 +12,10 @@ import { ISiteCreatedOptions } from './createFunctionApp/showSiteCreated';
export async function createSlot(context: IActionContext, node?: SlotsTreeItem): Promise<string> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotsTreeItem>(SlotsTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotsTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: SlotsTreeItem.contextValue
});
}
(<ISiteCreatedOptions>context).showCreatedNotification = true;

Просмотреть файл

@ -3,10 +3,20 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AzExtTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { deleteNode } from './deleteNode';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { ResolvedFunctionAppResource } from '../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../tree/SlotTreeItem';
export async function deleteFunctionApp(context: IActionContext, node?: AzExtTreeItem): Promise<void> {
await deleteNode(context, ProductionSlotTreeItem.contextValue, node)
export async function deleteFunctionApp(context: IActionContext, node?: SlotTreeItem): Promise<void> {
if (!node) {
node = await ext.rgApi.pickAppResource<SlotTreeItem>({ ...context, suppressCreatePick: true }, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
await node.deleteTreeItem(context);
}

Просмотреть файл

@ -4,11 +4,15 @@
*--------------------------------------------------------------------------------------------*/
import { AzExtTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
export async function deleteNode(context: IActionContext, expectedContextValue: string | RegExp, node?: AzExtTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker(expectedContextValue, { ...context, suppressCreatePick: true });
node = await ext.rgApi.pickAppResource<AzExtTreeItem>({ ...context, suppressCreatePick: true }, {
filter: functionFilter,
expectedChildContextValue: expectedContextValue
});
}
await node.deleteTreeItem(context);

Просмотреть файл

@ -7,14 +7,13 @@ import { SiteConfigResource } from '@azure/arm-appservice';
import { deploy as innerDeploy, getDeployFsPath, getDeployNode, IDeployContext, IDeployPaths, showDeployConfirmation } from '@microsoft/vscode-azext-azureappservice';
import { DialogResponses, IActionContext } from '@microsoft/vscode-azext-utils';
import * as vscode from 'vscode';
import { deploySubpathSetting, ProjectLanguage, remoteBuildSetting, ScmType } from '../../constants';
import { deploySubpathSetting, functionFilter, ProjectLanguage, remoteBuildSetting, ScmType } from '../../constants';
import { ext } from '../../extensionVariables';
import { addLocalFuncTelemetry } from '../../funcCoreTools/getLocalFuncCoreToolsVersion';
import { FuncVersion } from '../../FuncVersion';
import { localize } from '../../localize';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../../tree/SlotTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { dotnetUtils } from '../../utils/dotnetUtils';
import { isPathEqual } from '../../utils/fs';
import { getWorkspaceSetting } from '../../vsCodeConfig/settings';
@ -25,21 +24,24 @@ import { runPreDeployTask } from './runPreDeployTask';
import { validateRemoteBuild } from './validateRemoteBuild';
import { verifyAppSettings } from './verifyAppSettings';
export async function deployProductionSlot(context: IActionContext, target?: vscode.Uri | string | SlotTreeItemBase, functionAppId?: string | {}): Promise<void> {
await deploy(context, target, functionAppId, ProductionSlotTreeItem.contextValue);
export async function deployProductionSlot(context: IActionContext, target?: vscode.Uri | string | SlotTreeItem, functionAppId?: string | {}): Promise<void> {
await deploy(context, target, functionAppId, new RegExp(ResolvedFunctionAppResource.productionContextValue));
}
export async function deploySlot(context: IActionContext, target?: vscode.Uri | string | SlotTreeItemBase, functionAppId?: string | {}): Promise<void> {
await deploy(context, target, functionAppId, SlotTreeItem.contextValue);
export async function deploySlot(context: IActionContext, target?: vscode.Uri | string | SlotTreeItem, functionAppId?: string | {}): Promise<void> {
await deploy(context, target, functionAppId, new RegExp(ResolvedFunctionAppResource.pickSlotContextValue));
}
async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string | SlotTreeItemBase | undefined, arg2: string | {} | undefined, expectedContextValue: string): Promise<void> {
async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string | SlotTreeItem | undefined, arg2: string | {} | undefined, expectedContextValue: string | RegExp): Promise<void> {
const deployPaths: IDeployPaths = await getDeployFsPath(actionContext, arg1);
addLocalFuncTelemetry(actionContext, deployPaths.workspaceFolder.uri.fsPath);
const context: IDeployContext = Object.assign(actionContext, deployPaths, { defaultAppSetting: 'defaultFunctionAppToDeploy' });
const node: SlotTreeItemBase = await getDeployNode(context, ext.tree, arg1, arg2, expectedContextValue);
const node: SlotTreeItem = await getDeployNode(context, ext.rgApi.tree, arg1, arg2, async () => ext.rgApi.pickAppResource(context, {
filter: functionFilter,
expectedChildContextValue: expectedContextValue
}));
const [language, version]: [ProjectLanguage, FuncVersion] = await verifyInitForVSCode(context, context.effectiveDeployFsPath);
context.telemetry.properties.projectLanguage = language;
@ -113,7 +115,7 @@ async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string |
await notifyDeployComplete(context, node, context.workspaceFolder);
}
async function updateWorkerProcessTo64BitIfRequired(context: IDeployContext, siteConfig: SiteConfigResource, node: SlotTreeItemBase, language: ProjectLanguage): Promise<void> {
async function updateWorkerProcessTo64BitIfRequired(context: IDeployContext, siteConfig: SiteConfigResource, node: SlotTreeItem, language: ProjectLanguage): Promise<void> {
const functionProject: string | undefined = await tryGetFunctionProjectRoot(context, context.workspaceFolder);
if (functionProject === undefined) {
return;

Просмотреть файл

@ -10,12 +10,12 @@ import { ext } from '../../extensionVariables';
import { localize } from '../../localize';
import { RemoteFunctionsTreeItem } from '../../tree/remoteProject/RemoteFunctionsTreeItem';
import { RemoteFunctionTreeItem } from '../../tree/remoteProject/RemoteFunctionTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { SlotTreeItem } from '../../tree/SlotTreeItem';
import { nonNullValue } from '../../utils/nonNull';
import { uploadAppSettings } from '../appSettings/uploadAppSettings';
import { startStreamingLogs } from '../logstream/startStreamingLogs';
export async function notifyDeployComplete(context: IActionContext, node: SlotTreeItemBase, workspaceFolder: WorkspaceFolder): Promise<void> {
export async function notifyDeployComplete(context: IActionContext, node: SlotTreeItem, workspaceFolder: WorkspaceFolder): Promise<void> {
const deployComplete: string = localize('deployComplete', 'Deployment to "{0}" completed.', node.site.fullName);
const viewOutput: MessageItem = { title: localize('viewOutput', 'View output') };
const streamLogs: MessageItem = { title: localize('streamLogs', 'Stream logs') };
@ -59,7 +59,7 @@ export async function notifyDeployComplete(context: IActionContext, node: SlotTr
}
}
async function listHttpTriggerUrls(context: IActionContext, node: SlotTreeItemBase): Promise<void> {
async function listHttpTriggerUrls(context: IActionContext, node: SlotTreeItem): Promise<void> {
const children: AzExtTreeItem[] = await node.getCachedChildren(context);
const functionsNode: RemoteFunctionsTreeItem = <RemoteFunctionsTreeItem>children.find(n => n instanceof RemoteFunctionsTreeItem);
await node.treeDataProvider.refresh(context, functionsNode);

Просмотреть файл

@ -11,7 +11,7 @@ import { extensionVersionKey, ProjectLanguage, runFromPackageKey, workerRuntimeK
import { ext } from '../../extensionVariables';
import { FuncVersion, tryParseFuncVersion } from '../../FuncVersion';
import { localize } from '../../localize';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { SlotTreeItem } from '../../tree/SlotTreeItem';
import { isKnownWorkerRuntime, tryGetFunctionsWorkerRuntimeForProject } from '../../vsCodeConfig/settings';
/**
@ -19,7 +19,7 @@ import { isKnownWorkerRuntime, tryGetFunctionsWorkerRuntimeForProject } from '..
*/
type VerifyAppSettingBooleans = { doRemoteBuild: boolean | undefined; isConsumption: boolean };
export async function verifyAppSettings(context: IActionContext, node: SlotTreeItemBase, projectPath: string | undefined, version: FuncVersion, language: ProjectLanguage, bools: VerifyAppSettingBooleans): Promise<void> {
export async function verifyAppSettings(context: IActionContext, node: SlotTreeItem, projectPath: string | undefined, version: FuncVersion, language: ProjectLanguage, bools: VerifyAppSettingBooleans): Promise<void> {
const client = await node.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
if (appSettings.properties) {

Просмотреть файл

@ -5,27 +5,30 @@
import { DeploymentsTreeItem, editScmType } from "@microsoft/vscode-azext-azureappservice";
import { GenericTreeItem, IActionContext } from "@microsoft/vscode-azext-utils";
import { ScmType } from "../../constants";
import { functionFilter, ScmType } from "../../constants";
import { ext } from "../../extensionVariables";
import { ProductionSlotTreeItem } from "../../tree/ProductionSlotTreeItem";
import { SlotTreeItemBase } from "../../tree/SlotTreeItemBase";
import { ResolvedFunctionAppResource } from "../../tree/ResolvedFunctionAppResource";
import { isSlotTreeItem, SlotTreeItem } from "../../tree/SlotTreeItem";
export async function connectToGitHub(context: IActionContext, target?: GenericTreeItem): Promise<void> {
let node: ProductionSlotTreeItem | DeploymentsTreeItem;
let node: SlotTreeItem | DeploymentsTreeItem;
if (!target) {
node = await ext.tree.showTreeItemPicker<ProductionSlotTreeItem>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
} else {
node = <DeploymentsTreeItem>target.parent;
}
if (node?.parent instanceof SlotTreeItemBase) {
if (node.parent && isSlotTreeItem(node.parent)) {
await editScmType(context, node.site, node.subscription, ScmType.GitHub);
} else {
throw Error('Internal error: Action not supported.');
}
if (node instanceof ProductionSlotTreeItem) {
if (isSlotTreeItem(node)) {
if (node.deploymentsNode) {
await node.deploymentsNode.refresh(context);
}

Просмотреть файл

@ -5,15 +5,19 @@
import { DeploymentsTreeItem, disconnectRepo as disconnectRepository } from "@microsoft/vscode-azext-azureappservice";
import { IActionContext } from "@microsoft/vscode-azext-utils";
import { functionFilter } from "../../constants";
import { ext } from "../../extensionVariables";
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { isResolvedFunctionApp } from "../../tree/ResolvedFunctionAppResource";
export async function disconnectRepo(context: IActionContext, node?: DeploymentsTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<DeploymentsTreeItem>(DeploymentsTreeItem.contextValueConnected, context);
node = await ext.rgApi.pickAppResource<DeploymentsTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: DeploymentsTreeItem.contextValueConnected
});
}
if (node.parent instanceof SlotTreeItemBase) {
if (isResolvedFunctionApp(node.parent)) {
await disconnectRepository(context, node.site, node.subscription);
await node.refresh(context);
} else {

Просмотреть файл

@ -5,11 +5,15 @@
import { DeploymentTreeItem } from "@microsoft/vscode-azext-azureappservice";
import { IActionContext } from "@microsoft/vscode-azext-utils";
import { functionFilter } from "../../constants";
import { ext } from "../../extensionVariables";
export async function redeployDeployment(context: IActionContext, node?: DeploymentTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<DeploymentTreeItem>(DeploymentTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<DeploymentTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: DeploymentTreeItem.contextValue
});
}
await node.redeployDeployment(context);
}

Просмотреть файл

@ -5,11 +5,15 @@
import { DeploymentTreeItem } from "@microsoft/vscode-azext-azureappservice";
import { IActionContext } from "@microsoft/vscode-azext-utils";
import { functionFilter } from "../../constants";
import { ext } from "../../extensionVariables";
export async function viewCommitInGitHub(context: IActionContext, node?: DeploymentTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<DeploymentTreeItem>('deployment/github', context);
node = await ext.rgApi.pickAppResource<DeploymentTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: 'deployment/github'
});
}
await node.viewCommitInGitHub(context);
}

Просмотреть файл

@ -5,11 +5,15 @@
import { DeploymentTreeItem } from "@microsoft/vscode-azext-azureappservice";
import { IActionContext } from "@microsoft/vscode-azext-utils";
import { functionFilter } from "../../constants";
import { ext } from "../../extensionVariables";
export async function viewDeploymentLogs(context: IActionContext, node?: DeploymentTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<DeploymentTreeItem>(DeploymentTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<DeploymentTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: DeploymentTreeItem.contextValue
});
}
await node.viewDeploymentLogs(context);
}

Просмотреть файл

@ -5,11 +5,15 @@
import { AppSettingTreeItem } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
export async function editAppSetting(context: IActionContext, node?: AppSettingTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<AppSettingTreeItem>(AppSettingTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<AppSettingTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(AppSettingTreeItem.contextValue)
});
}
await node.edit(context);

Просмотреть файл

@ -6,6 +6,7 @@
import { SiteClient } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext, parseError } from '@microsoft/vscode-azext-utils';
import { window } from 'vscode';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { FuncVersion } from '../FuncVersion';
import { localize } from '../localize';
@ -19,7 +20,10 @@ export async function executeFunction(context: IActionContext, node?: FunctionTr
context.telemetry.eventVersion = 2;
if (!node) {
const noItemFoundErrorMessage: string = localize('noFunctions', 'No functions found.');
node = await ext.tree.showTreeItemPicker<FunctionTreeItemBase>(/Function;/i, { ...context, noItemFoundErrorMessage });
node = await ext.rgApi.pickAppResource<FunctionTreeItemBase>({ ...context, noItemFoundErrorMessage }, {
filter: functionFilter,
expectedChildContextValue: /Function;/i
});
}
const client: SiteClient | undefined = node instanceof RemoteFunctionTreeItem ? await node.parent.parent.site.createClient(context) : undefined;

Просмотреть файл

@ -7,7 +7,7 @@ import { AzureWizardExecuteStep, IActionContext } from '@microsoft/vscode-azext-
import * as fse from 'fs-extra';
import * as path from 'path';
import { DebugConfiguration, MessageItem, TaskDefinition, WorkspaceFolder } from 'vscode';
import { deploySubpathSetting, func, funcVersionSetting, gitignoreFileName, launchFileName, preDeployTaskSetting, ProjectLanguage, projectLanguageSetting, projectSubpathSetting, settingsFileName, tasksFileName } from '../../../constants';
import { deploySubpathSetting, extensionId, func, funcVersionSetting, gitignoreFileName, launchFileName, preDeployTaskSetting, ProjectLanguage, projectLanguageSetting, projectSubpathSetting, settingsFileName, tasksFileName } from '../../../constants';
import { ext } from '../../../extensionVariables';
import { FuncVersion } from '../../../FuncVersion';
import { localize } from '../../../localize';
@ -251,7 +251,7 @@ export abstract class InitVSCodeStepBase extends AzureWizardExecuteStep<IProject
context,
extensionsJsonPath,
(data: IExtensionsJson): {} => {
const recommendations: string[] = ['ms-azuretools.vscode-azurefunctions'];
const recommendations: string[] = [extensionId];
if (this.getRecommendedExtensions) {
recommendations.push(...this.getRecommendedExtensions(language));
}

Просмотреть файл

@ -8,22 +8,26 @@ import { SiteLogsConfig, StringDictionary } from '@azure/arm-appservice';
import * as appservice from '@microsoft/vscode-azext-azureappservice';
import { ParsedSite } from '@microsoft/vscode-azext-azureappservice';
import { AzExtTreeItem, DialogResponses, IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../../constants';
import { ext } from '../../extensionVariables';
import { localize } from '../../localize';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { RemoteFunctionTreeItem } from '../../tree/remoteProject/RemoteFunctionTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource';
import { isSlotTreeItem, SlotTreeItem } from '../../tree/SlotTreeItem';
import { createAppInsightsClient } from '../../utils/azureClients';
import { nonNullProp } from '../../utils/nonNull';
import { openUrl } from '../../utils/openUrl';
import { enableFileLogging } from './enableFileLogging';
export async function startStreamingLogs(context: IActionContext, treeItem?: SlotTreeItemBase | RemoteFunctionTreeItem): Promise<void> {
export async function startStreamingLogs(context: IActionContext, treeItem?: SlotTreeItem | RemoteFunctionTreeItem): Promise<void> {
if (!treeItem) {
treeItem = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
treeItem = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const site: ParsedSite = treeItem instanceof SlotTreeItemBase ? treeItem.site : treeItem.parent.parent.site;
const site: ParsedSite = isSlotTreeItem(treeItem) ? treeItem.site : treeItem.parent.parent.site;
if (site.isLinux) {
try {
@ -61,7 +65,7 @@ async function openLiveMetricsStream(context: IActionContext, site: ParsedSite,
// https://github.com/microsoft/vscode-azurefunctions/issues/1432
throw new Error(localize('mustConfigureAI', 'You must configure Application Insights to stream logs on Linux Function Apps.'));
} else {
const aiClient: ApplicationInsightsManagementClient = await createAppInsightsClient([context, node]);
const aiClient: ApplicationInsightsManagementClient = await createAppInsightsClient([context, node.subscription]);
const components: ApplicationInsightsManagementModels.ApplicationInsightsComponentListResult = await aiClient.components.list();
const component: ApplicationInsightsManagementModels.ApplicationInsightsComponent | undefined = components.find(c => c.instrumentationKey === aiKey);
if (!component) {

Просмотреть файл

@ -6,16 +6,20 @@
import * as appservice from '@microsoft/vscode-azext-azureappservice';
import { ParsedSite } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../../constants';
import { ext } from '../../extensionVariables';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { RemoteFunctionTreeItem } from '../../tree/remoteProject/RemoteFunctionTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource';
import { isSlotTreeItem, SlotTreeItem } from '../../tree/SlotTreeItem';
export async function stopStreamingLogs(context: IActionContext, node?: SlotTreeItemBase | RemoteFunctionTreeItem): Promise<void> {
export async function stopStreamingLogs(context: IActionContext, node?: SlotTreeItem | RemoteFunctionTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, { ...context, suppressCreatePick: true });
node = await ext.rgApi.pickAppResource<SlotTreeItem>({ ...context, suppressCreatePick: true }, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const site: ParsedSite = node instanceof SlotTreeItemBase ? node.site : node.parent.parent.site;
const site: ParsedSite = isSlotTreeItem(node) ? node.site : node.parent.parent.site;
await appservice.stopStreamingLogs(site, node.logStreamPath);
}

Просмотреть файл

@ -4,14 +4,8 @@
*--------------------------------------------------------------------------------------------*/
import { openInPortal as uiOpenInPortal } from '@microsoft/vscode-azext-azureutils';
import { AzExtTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { ext } from '../extensionVariables';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { AzExtTreeItem, IActionContext, nonNullProp } from '@microsoft/vscode-azext-utils';
export async function openInPortal(context: IActionContext, node?: AzExtTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<AzExtTreeItem>(ProductionSlotTreeItem.contextValue, context);
}
await uiOpenInPortal(node, node.fullId);
export async function openDeploymentInPortal(_context: IActionContext, node: AzExtTreeItem): Promise<void> {
await uiOpenInPortal(node, `${nonNullProp(node, 'parent').parent?.id}/Deployments/${nonNullProp(node, 'id')}`);
}

Просмотреть файл

@ -5,11 +5,10 @@
import { AppSettingsTreeItem, AppSettingTreeItem, registerSiteCommand } from '@microsoft/vscode-azext-azureappservice';
import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, registerCommand } from '@microsoft/vscode-azext-utils';
import { commands } from 'vscode';
import { ext } from '../extensionVariables';
import { installOrUpdateFuncCoreTools } from '../funcCoreTools/installOrUpdateFuncCoreTools';
import { uninstallFuncCoreTools } from '../funcCoreTools/uninstallFuncCoreTools';
import { SlotTreeItem } from '../tree/SlotTreeItem';
import { ResolvedFunctionAppResource } from '../tree/ResolvedFunctionAppResource';
import { addBinding } from './addBinding/addBinding';
import { decryptLocalSettings } from './appSettings/decryptLocalSettings';
import { downloadAppSettings } from './appSettings/downloadAppSettings';
@ -40,7 +39,7 @@ import { initProjectForVSCode } from './initProjectForVSCode/initProjectForVSCod
import { startStreamingLogs } from './logstream/startStreamingLogs';
import { stopStreamingLogs } from './logstream/stopStreamingLogs';
import { openFile } from './openFile';
import { openInPortal } from './openInPortal';
import { openDeploymentInPortal } from './openInPortal';
import { pickFuncProcess } from './pickFuncProcess';
import { startRemoteDebug } from './remoteDebug/startRemoteDebug';
import { remoteDebugJavaFunctionApp } from './remoteDebugJava/remoteDebugJavaFunctionApp';
@ -54,9 +53,9 @@ import { viewProperties } from './viewProperties';
export function registerCommands(): void {
registerCommand('azureFunctions.addBinding', addBinding);
registerCommand('azureFunctions.appSettings.add', async (context: IActionContext, node?: AzExtParentTreeItem) => await createChildNode(context, AppSettingsTreeItem.contextValue, node));
registerCommand('azureFunctions.appSettings.add', async (context: IActionContext, node?: AzExtParentTreeItem) => await createChildNode(context, new RegExp(AppSettingsTreeItem.contextValue), node));
registerCommand('azureFunctions.appSettings.decrypt', decryptLocalSettings);
registerCommand('azureFunctions.appSettings.delete', async (context: IActionContext, node?: AzExtTreeItem) => await deleteNode(context, AppSettingTreeItem.contextValue, node));
registerCommand('azureFunctions.appSettings.delete', async (context: IActionContext, node?: AzExtTreeItem) => await deleteNode(context, new RegExp(AppSettingTreeItem.contextValue), node));
registerCommand('azureFunctions.appSettings.download', downloadAppSettings);
registerCommand('azureFunctions.appSettings.edit', editAppSetting);
registerCommand('azureFunctions.appSettings.encrypt', encryptLocalSettings);
@ -74,7 +73,7 @@ export function registerCommands(): void {
registerCommand('azureFunctions.createSlot', createSlot);
registerCommand('azureFunctions.deleteFunction', deleteFunction);
registerCommand('azureFunctions.deleteFunctionApp', deleteFunctionApp);
registerCommand('azureFunctions.deleteSlot', async (context: IActionContext, node?: AzExtTreeItem) => await deleteNode(context, SlotTreeItem.contextValue, node));
registerCommand('azureFunctions.deleteSlot', async (context: IActionContext, node?: AzExtTreeItem) => await deleteNode(context, ResolvedFunctionAppResource.pickSlotContextValue, node));
registerCommand('azureFunctions.disableFunction', disableFunction);
registerSiteCommand('azureFunctions.deploy', deployProductionSlot);
registerSiteCommand('azureFunctions.deploySlot', deploySlot);
@ -83,14 +82,11 @@ export function registerCommands(): void {
registerCommand('azureFunctions.executeFunction', executeFunction);
registerCommand('azureFunctions.initProjectForVSCode', initProjectForVSCode);
registerCommand('azureFunctions.installOrUpdateFuncCoreTools', installOrUpdateFuncCoreTools);
registerCommand('azureFunctions.loadMore', async (context: IActionContext, node: AzExtTreeItem) => await ext.tree.loadMore(node, context));
registerCommand('azureFunctions.openFile', openFile);
registerCommand('azureFunctions.openInPortal', openInPortal);
registerCommand('azureFunctions.openInPortal', openDeploymentInPortal);
registerCommand('azureFunctions.pickProcess', pickFuncProcess);
registerSiteCommand('azureFunctions.redeploy', redeployDeployment);
registerCommand('azureFunctions.refresh', async (context: IActionContext, node?: AzExtTreeItem) => await ext.tree.refresh(context, node));
registerCommand('azureFunctions.restartFunctionApp', restartFunctionApp);
registerCommand('azureFunctions.selectSubscriptions', () => commands.executeCommand('azure-account.selectSubscriptions'));
registerCommand('azureFunctions.setAzureWebJobsStorage', setAzureWebJobsStorage);
registerCommand('azureFunctions.startFunctionApp', startFunctionApp);
registerCommand('azureFunctions.startJavaRemoteDebug', remoteDebugJavaFunctionApp);

Просмотреть файл

@ -7,14 +7,18 @@ import { SiteConfig } from '@azure/arm-appservice';
import * as appservice from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import * as vscode from 'vscode';
import { functionFilter } from '../../constants';
import { ext } from '../../extensionVariables';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../../tree/SlotTreeItem';
import { getRemoteDebugLanguage } from './getRemoteDebugLanguage';
export async function startRemoteDebug(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function startRemoteDebug(context: IActionContext, node?: SlotTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const siteClient = await node.site.createClient(context);

Просмотреть файл

@ -7,19 +7,23 @@ import { SiteConfigResource, StringDictionary, User } from '@azure/arm-appservic
import { SiteClient } from '@microsoft/vscode-azext-azureappservice';
import { DialogResponses, findFreePort, IActionContext } from '@microsoft/vscode-azext-utils';
import * as vscode from 'vscode';
import { functionFilter } from '../../constants';
import { ext } from '../../extensionVariables';
import { localize } from '../../localize';
import { ProductionSlotTreeItem } from '../../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../../tree/SlotTreeItem';
import { openUrl } from '../../utils/openUrl';
import { DebugProxy } from './DebugProxy';
const HTTP_PLATFORM_DEBUG_PORT: string = '8898';
const JAVA_OPTS: string = `-Djava.net.preferIPv4Stack=true -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=127.0.0.1:${HTTP_PLATFORM_DEBUG_PORT}`;
export async function remoteDebugJavaFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function remoteDebugJavaFunctionApp(context: IActionContext, node?: SlotTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const client: SiteClient = await node.site.createClient(context);
const portNumber: number = await findFreePort();

Просмотреть файл

@ -5,11 +5,15 @@
import { AppSettingTreeItem } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
export async function renameAppSetting(context: IActionContext, node?: AppSettingTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<AppSettingTreeItem>(AppSettingTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<AppSettingTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(AppSettingTreeItem.contextValue)
});
}
await node.rename(context);

Просмотреть файл

@ -4,11 +4,11 @@
*--------------------------------------------------------------------------------------------*/
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
import { SlotTreeItem } from '../tree/SlotTreeItem';
import { startFunctionApp } from './startFunctionApp';
import { stopFunctionApp } from './stopFunctionApp';
export async function restartFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function restartFunctionApp(context: IActionContext, node?: SlotTreeItem): Promise<void> {
node = await stopFunctionApp(context, node);
await startFunctionApp(context, node);
}

Просмотреть файл

@ -5,14 +5,18 @@
import { SiteClient } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { localize } from '../localize';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../tree/SlotTreeItem';
export async function startFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<void> {
export async function startFunctionApp(context: IActionContext, node?: SlotTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const client: SiteClient = await node.site.createClient(context);

Просмотреть файл

@ -5,14 +5,18 @@
import { SiteClient } from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { localize } from '../localize';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
import { ResolvedFunctionAppResource } from '../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../tree/SlotTreeItem';
export async function stopFunctionApp(context: IActionContext, node?: SlotTreeItemBase): Promise<SlotTreeItemBase> {
export async function stopFunctionApp(context: IActionContext, node?: SlotTreeItem): Promise<SlotTreeItem> {
if (!node) {
node = await ext.tree.showTreeItemPicker<SlotTreeItemBase>(ProductionSlotTreeItem.contextValue, context);
node = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.productionContextValue)
});
}
const client: SiteClient = await node.site.createClient(context);

Просмотреть файл

@ -5,15 +5,20 @@
import * as appservice from '@microsoft/vscode-azext-azureappservice';
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { ResolvedFunctionAppResource } from '../tree/ResolvedFunctionAppResource';
import { SlotTreeItem } from '../tree/SlotTreeItem';
export async function swapSlot(context: IActionContext, sourceSlotNode?: SlotTreeItem): Promise<void> {
if (!sourceSlotNode) {
sourceSlotNode = await ext.tree.showTreeItemPicker<SlotTreeItem>(SlotTreeItem.contextValue, { ...context, suppressCreatePick: true });
sourceSlotNode = await ext.rgApi.pickAppResource<SlotTreeItem>({ ...context, suppressCreatePick: true }, {
filter: functionFilter,
expectedChildContextValue: new RegExp(ResolvedFunctionAppResource.pickSlotContextValue)
});
}
const deploymentSlots: SlotTreeItem[] = <SlotTreeItem[]>await sourceSlotNode.parent.getCachedChildren(context);
const deploymentSlots: SlotTreeItem[] = <SlotTreeItem[]>await sourceSlotNode.parent?.getCachedChildren(context);
await appservice.swapSlot(context, sourceSlotNode.site, deploymentSlots.map(ds => ds.site));
await sourceSlotNode.parent.parent.refresh(context);
await sourceSlotNode.parent?.parent?.refresh(context);
}

Просмотреть файл

@ -5,6 +5,7 @@
import { IActionContext } from '@microsoft/vscode-azext-utils';
import { window } from 'vscode';
import { functionFilter } from '../constants';
import { ext } from '../extensionVariables';
import { FuncVersion } from '../FuncVersion';
import { localize } from '../localize';
@ -22,7 +23,10 @@ async function updateDisabledState(context: IActionContext, node: FunctionTreeIt
if (!node) {
const expectedContextValue: RegExp = new RegExp(`Function;.*;${isDisabled ? 'Enabled' : 'Disabled'};`);
const noItemFoundErrorMessage: string = isDisabled ? localize('noEnabledFuncs', 'No enabled functions found.') : localize('noDisabledFuncs', 'No disabled functions found.');
node = await ext.tree.showTreeItemPicker<FunctionTreeItemBase>(expectedContextValue, { ...context, noItemFoundErrorMessage });
node = await ext.rgApi.pickAppResource<FunctionTreeItemBase>({ ...context, noItemFoundErrorMessage }, {
filter: functionFilter,
expectedChildContextValue: expectedContextValue
});
}
const version: FuncVersion = await node.parent.parent.getVersion(context);

Просмотреть файл

@ -5,18 +5,12 @@
import { IActionContext, openReadOnlyJson } from '@microsoft/vscode-azext-utils';
import { Uri, window } from 'vscode';
import { ext } from '../extensionVariables';
import { localize } from '../localize';
import { LocalFunctionTreeItem } from '../tree/localProject/LocalFunctionTreeItem';
import { ProductionSlotTreeItem } from '../tree/ProductionSlotTreeItem';
import { RemoteFunctionTreeItem } from '../tree/remoteProject/RemoteFunctionTreeItem';
import { SlotTreeItemBase } from '../tree/SlotTreeItemBase';
export async function viewProperties(context: IActionContext, node?: SlotTreeItemBase | RemoteFunctionTreeItem | LocalFunctionTreeItem): Promise<void> {
if (!node) {
node = await ext.tree.showTreeItemPicker<ProductionSlotTreeItem>(ProductionSlotTreeItem.contextValue, context);
}
import { SlotTreeItem } from '../tree/SlotTreeItem';
export async function viewProperties(context: IActionContext, node: SlotTreeItem | RemoteFunctionTreeItem | LocalFunctionTreeItem): Promise<void> {
if (node instanceof LocalFunctionTreeItem) {
if (!node.functionJsonPath) {
throw new Error(localize('viewPropsNotSupported', 'View function properties is not supported for this project type.'));
@ -24,8 +18,8 @@ export async function viewProperties(context: IActionContext, node?: SlotTreeIte
await window.showTextDocument(Uri.file(node.functionJsonPath));
} else {
let data: {};
if (node instanceof SlotTreeItemBase) {
const siteNode: SlotTreeItemBase = node;
if (node instanceof SlotTreeItem) {
const siteNode: SlotTreeItem = node;
await node.runWithTemporaryDescription(context, localize('retrievingProps', 'Retrieving properties...'), async () => {
// `siteConfig` already exists on `node.site`, but has very limited properties for some reason. We want to get the full site config
const client = await siteNode.site.createClient(context);

Просмотреть файл

@ -5,6 +5,7 @@
import { localize } from "./localize";
export const extensionId: string = 'ms-azuretools.vscode-azurefunctions';
export const projectLanguageSetting: string = 'projectLanguage';
export const funcVersionSetting: string = 'projectRuntime'; // Using this name for the sake of backwards compatability even though it's not the most accurate
export const projectSubpathSetting: string = 'projectSubpath';
@ -98,3 +99,8 @@ export const viewOutput: string = localize('viewOutput', 'View Output');
export const previewDescription: string = localize('preview', '(Preview)');
export const webProvider: string = 'Microsoft.Web';
export const functionFilter = {
type: 'microsoft.web/sites',
kind: 'functionapp',
};

Просмотреть файл

@ -13,7 +13,7 @@ import { initProjectForVSCode } from '../commands/initProjectForVSCode/initProje
import { ProjectLanguage } from '../constants';
import { ext } from '../extensionVariables';
import { localize } from '../localize';
import { SlotTreeItemBase } from "../tree/SlotTreeItemBase";
import { SlotTreeItem } from "../tree/SlotTreeItem";
import { getNameFromId } from '../utils/azure';
import { requestUtils } from '../utils/requestUtils';
import { getRequiredQueryParameter } from './handleUri';
@ -32,7 +32,7 @@ export async function setupProjectFolder(uri: vscode.Uri, vsCodeFilePathUri: vsc
await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: localize('settingUpFunctionAppLocalProjInfoMessage', `Setting up project for function app '${functionAppName}' with language '${language}'.`) }, async () => {
// NOTE: We don't want to download app content for compiled languages.
const slotTreeItem: SlotTreeItemBase | undefined = await ext.tree.findTreeItem(resourceId, { ...context, loadAll: true });
const slotTreeItem: SlotTreeItem | undefined = await ext.rgApi.tree.findTreeItem(resourceId, { ...context, loadAll: true });
if (!slotTreeItem) {
throw new Error(localize('failedToFindApp', 'Failed to find function app with id "{0}"', resourceId));
}

Просмотреть файл

@ -7,7 +7,7 @@
import { registerAppServiceExtensionVariables } from '@microsoft/vscode-azext-azureappservice';
import { registerAzureUtilsExtensionVariables } from '@microsoft/vscode-azext-azureutils';
import { AzExtTreeDataProvider, callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, createExperimentationService, IActionContext, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils';
import { callWithTelemetryAndErrorHandling, createApiProvider, createAzExtOutputChannel, createExperimentationService, IActionContext, registerErrorHandler, registerEvent, registerReportIssueCommand, registerUIExtensionVariables } from '@microsoft/vscode-azext-utils';
import { AzureExtensionApiProvider } from '@microsoft/vscode-azext-utils/api';
import * as vscode from 'vscode';
import { createFunctionFromApi } from './commands/api/createFunctionFromApi';
@ -16,7 +16,7 @@ import { revealTreeItem } from './commands/api/revealTreeItem';
import { uploadAppSettingsFromApi } from './commands/api/uploadAppSettingsFromApi';
import { runPostFunctionCreateStepsFromCache } from './commands/createFunction/FunctionCreateStepBase';
import { registerCommands } from './commands/registerCommands';
import { func } from './constants';
import { extensionId, func } from './constants';
import { FuncTaskProvider } from './debug/FuncTaskProvider';
import { JavaDebugProvider } from './debug/JavaDebugProvider';
import { NodeDebugProvider } from './debug/NodeDebugProvider';
@ -26,8 +26,10 @@ import { handleUri } from './downloadAzureProject/handleUri';
import { ext } from './extensionVariables';
import { registerFuncHostTaskEvents } from './funcCoreTools/funcHostTask';
import { validateFuncCoreToolsIsLatest } from './funcCoreTools/validateFuncCoreToolsIsLatest';
import { FunctionAppResolver } from './FunctionAppResolver';
import { getResourceGroupsApi } from './getExtensionApi';
import { FunctionsLocalResourceProvider } from './LocalResourceProvider';
import { CentralTemplateProvider } from './templates/CentralTemplateProvider';
import { AzureAccountTreeItemWithProjects } from './tree/AzureAccountTreeItemWithProjects';
import { AzureFunctionsExtensionApi } from './vscode-azurefunctions.api';
import { verifyVSCodeConfigOnActivate } from './vsCodeConfig/verifyVSCodeConfigOnActivate';
@ -49,12 +51,6 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
void validateFuncCoreToolsIsLatest();
ext.azureAccountTreeItem = new AzureAccountTreeItemWithProjects();
context.subscriptions.push(ext.azureAccountTreeItem);
ext.tree = new AzExtTreeDataProvider(ext.azureAccountTreeItem, 'azureFunctions.loadMore');
ext.treeView = vscode.window.createTreeView('azFuncTree', { treeDataProvider: ext.tree, showCollapseAll: true });
context.subscriptions.push(ext.treeView);
const validateEventId: string = 'azureFunctions.validateFunctionProjects';
void callWithTelemetryAndErrorHandling(validateEventId, async (actionContext: IActionContext) => {
await verifyVSCodeConfigOnActivate(actionContext, vscode.workspace.workspaceFolders);
@ -92,6 +88,10 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
}));
ext.experimentationService = await createExperimentationService(context);
ext.rgApi = await getResourceGroupsApi();
ext.rgApi.registerApplicationResourceResolver(extensionId, new FunctionAppResolver());
ext.rgApi.registerLocalResourceProvider('func', new FunctionsLocalResourceProvider());
});
return createApiProvider([<AzureFunctionsExtensionApi>{

Просмотреть файл

@ -3,8 +3,9 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AzExtTreeDataProvider, AzExtTreeItem, IActionContext, IAzExtOutputChannel, IExperimentationServiceAdapter } from "@microsoft/vscode-azext-utils";
import { ExtensionContext, TreeView } from "vscode";
import { IActionContext, IAzExtOutputChannel, IExperimentationServiceAdapter } from "@microsoft/vscode-azext-utils";
import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi";
import { ExtensionContext } from "vscode";
import { func } from "./constants";
import { CentralTemplateProvider } from "./templates/CentralTemplateProvider";
import { AzureAccountTreeItemWithProjects } from "./tree/AzureAccountTreeItemWithProjects";
@ -44,8 +45,6 @@ class ActionVariable<T> {
*/
export namespace ext {
export let context: ExtensionContext;
export let tree: AzExtTreeDataProvider;
export let treeView: TreeView<AzExtTreeItem>;
export let azureAccountTreeItem: AzureAccountTreeItemWithProjects;
export let outputChannel: IAzExtOutputChannel;
// eslint-disable-next-line prefer-const
@ -54,6 +53,7 @@ export namespace ext {
export const prefix: string = 'azureFunctions';
export let experimentationService: IExperimentationServiceAdapter;
export const templateProvider = new ActionVariable<CentralTemplateProvider>('_centralTemplateProvider');
export let rgApi: AzureHostExtensionApi;
}
export enum TemplateSource {

31
src/getExtensionApi.ts Normal file
Просмотреть файл

@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AzureExtensionApiProvider } from "@microsoft/vscode-azext-utils/api";
import { AzureHostExtensionApi } from "@microsoft/vscode-azext-utils/hostapi";
import { Extension, extensions } from "vscode";
import { localize } from "./localize";
export async function getApiExport<T>(extensionId: string): Promise<T | undefined> {
const extension: Extension<T> | undefined = extensions.getExtension(extensionId);
if (extension) {
if (!extension.isActive) {
await extension.activate();
}
return extension.exports;
}
return undefined;
}
export async function getResourceGroupsApi(): Promise<AzureHostExtensionApi> {
const rgApiProvider = await getApiExport<AzureExtensionApiProvider>('ms-azuretools.vscode-azureresourcegroups');
if (rgApiProvider) {
return rgApiProvider.getApi<AzureHostExtensionApi>('0.0.1');
} else {
throw new Error(localize('noResourceGroupExt', 'Could not find the Azure Resource Groups extension'));
}
}

Просмотреть файл

@ -1,46 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ParsedSite } from '@microsoft/vscode-azext-azureappservice';
import { AzExtTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { SlotsTreeItem } from './SlotsTreeItem';
import { SlotTreeItem } from './SlotTreeItem';
import { SlotTreeItemBase } from './SlotTreeItemBase';
import { SubscriptionTreeItem } from './SubscriptionTreeItem';
export class ProductionSlotTreeItem extends SlotTreeItemBase {
public static contextValue: string = 'azFuncProductionSlot';
public readonly contextValue: string = ProductionSlotTreeItem.contextValue;
private readonly _slotsTreeItem: SlotsTreeItem;
public constructor(parent: SubscriptionTreeItem, site: ParsedSite) {
super(parent, site);
this._slotsTreeItem = new SlotsTreeItem(this);
}
public get label(): string {
return this.site.fullName;
}
public async loadMoreChildrenImpl(clearCache: boolean, context: IActionContext): Promise<AzExtTreeItem[]> {
const children: AzExtTreeItem[] = await super.loadMoreChildrenImpl(clearCache, context);
children.push(this._slotsTreeItem);
return children;
}
public async pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): Promise<AzExtTreeItem | undefined> {
for (const expectedContextValue of expectedContextValues) {
switch (expectedContextValue) {
case SlotsTreeItem.contextValue:
case SlotTreeItem.contextValue:
return this._slotsTreeItem;
default:
}
}
return super.pickTreeItemImpl(expectedContextValues);
}
}

Просмотреть файл

@ -0,0 +1,320 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Site, SiteConfig, SiteSourceControl, StringDictionary } from "@azure/arm-appservice";
import { AppSettingsTreeItem, AppSettingTreeItem, DeleteLastServicePlanStep, DeleteSiteStep, DeploymentsTreeItem, DeploymentTreeItem, getFile, IDeleteSiteWizardContext, LogFilesTreeItem, ParsedSite, SiteFilesTreeItem } from "@microsoft/vscode-azext-azureappservice";
import { AzExtTreeItem, AzureWizard, DeleteConfirmationStep, IActionContext, ISubscriptionContext, nonNullValue, TreeItemIconPath } from "@microsoft/vscode-azext-utils";
import { ResolvedAppResourceBase } from "@microsoft/vscode-azext-utils/hostapi";
import { runFromPackageKey } from "../constants";
import { IParsedHostJson, parseHostJson } from "../funcConfig/host";
import { FuncVersion, latestGAVersion, tryParseFuncVersion } from "../FuncVersion";
import { localize } from "../localize";
import { createActivityContext } from "../utils/activityUtils";
import { envUtils } from "../utils/envUtils";
import { treeUtils } from "../utils/treeUtils";
import { ApplicationSettings, FuncHostRequest } from "./IProjectTreeItem";
import { matchesAnyPart, ProjectResource, ProjectSource } from "./projectContextValues";
import { RemoteFunctionsTreeItem } from "./remoteProject/RemoteFunctionsTreeItem";
import { SlotsTreeItem } from "./SlotsTreeItem";
import { SlotTreeItem } from "./SlotTreeItem";
export function isResolvedFunctionApp(ti: unknown): ti is ResolvedAppResourceBase {
return (ti as unknown as ResolvedFunctionAppResource).instance === ResolvedFunctionAppResource.instance;
}
export class ResolvedFunctionAppResource implements ResolvedAppResourceBase {
public site: ParsedSite;
private _subscription: ISubscriptionContext;
public logStreamPath: string = '';
public appSettingsTreeItem: AppSettingsTreeItem;
public deploymentsNode: DeploymentsTreeItem | undefined;
public readonly source: ProjectSource = ProjectSource.Remote;
public static instance = 'resolvedFunctionApp';
public readonly instance = ResolvedFunctionAppResource.instance;
public contextValuesToAdd?: string[] | undefined;
public maskedValuesToAdd: string[] = [];
private _slotsTreeItem: SlotsTreeItem;
private _functionsTreeItem: RemoteFunctionsTreeItem | undefined;
private _logFilesTreeItem: LogFilesTreeItem;
private _siteFilesTreeItem: SiteFilesTreeItem;
private _cachedVersion: FuncVersion | undefined;
private _cachedHostJson: IParsedHostJson | undefined;
private _cachedIsConsumption: boolean | undefined;
public static pickSlotContextValue: RegExp = new RegExp(/azFuncSlot(?!s)/);
public static productionContextValue: string = 'azFuncProductionSlot';
public static slotContextValue: string = 'azFuncSlot';
commandId?: string | undefined;
tooltip?: string | undefined;
commandArgs?: unknown[] | undefined;
public constructor(subscription: ISubscriptionContext, site: Site) {
this.site = new ParsedSite(site, subscription);
this._subscription = subscription;
this.contextValuesToAdd = [this.site.isSlot ? ResolvedFunctionAppResource.slotContextValue : ResolvedFunctionAppResource.productionContextValue];
const valuesToMask = [
this.site.siteName, this.site.slotName, this.site.defaultHostName, this.site.resourceGroup,
this.site.planName, this.site.planResourceGroup, this.site.kuduHostName, this.site.gitUrl,
this.site.rawSite.repositorySiteName, ...(this.site.rawSite.hostNames || []), ...(this.site.rawSite.enabledHostNames || [])
];
for (const v of valuesToMask) {
if (v) {
this.maskedValuesToAdd.push(v);
}
}
}
public get name(): string {
return this.label;
}
public get label(): string {
return this.site.slotName ?? this.site.fullName;
}
public get id(): string {
return this.site.id;
}
public get logStreamLabel(): string {
return this.site.fullName;
}
public async getHostRequest(): Promise<FuncHostRequest> {
return { url: this.site.defaultHostUrl };
}
public get description(): string | undefined {
return this._state?.toLowerCase() !== 'running' ? this._state : undefined;
}
public get iconPath(): TreeItemIconPath {
const proxyTree: SlotTreeItem = this as unknown as SlotTreeItem;
return treeUtils.getIconPath(proxyTree.contextValue);
}
private get _state(): string | undefined {
return this.site.rawSite.state;
}
public hasMoreChildrenImpl(): boolean {
return false;
}
/**
* NOTE: We need to be extra careful in this method because it blocks many core scenarios (e.g. deploy) if the tree item is listed as invalid
*/
public async refreshImpl(context: IActionContext): Promise<void> {
this._cachedVersion = undefined;
this._cachedHostJson = undefined;
this._cachedIsConsumption = undefined;
const client = await this.site.createClient(context);
this.site = new ParsedSite(nonNullValue(await client.getSite(), 'site'), this._subscription);
}
public async getVersion(context: IActionContext): Promise<FuncVersion> {
let result: FuncVersion | undefined = this._cachedVersion;
if (result === undefined) {
let version: FuncVersion | undefined;
try {
const client = await this.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
version = tryParseFuncVersion(appSettings.properties && appSettings.properties.FUNCTIONS_EXTENSION_VERSION);
} catch {
// ignore and use default
}
result = version || latestGAVersion;
this._cachedVersion = result;
}
return result;
}
public async getHostJson(context: IActionContext): Promise<IParsedHostJson> {
let result: IParsedHostJson | undefined = this._cachedHostJson;
if (!result) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let data: any;
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
data = JSON.parse((await getFile(context, this.site, 'site/wwwroot/host.json')).data);
} catch {
// ignore and use default
}
const version: FuncVersion = await this.getVersion(context);
result = parseHostJson(data, version);
this._cachedHostJson = result;
}
return result;
}
public async getApplicationSettings(context: IActionContext): Promise<ApplicationSettings> {
const client = await this.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
return appSettings.properties || {};
}
public async setApplicationSetting(context: IActionContext, key: string, value: string): Promise<void> {
const client = await this.site.createClient(context);
const settings: StringDictionary = await client.listApplicationSettings();
if (!settings.properties) {
settings.properties = {};
}
settings.properties[key] = value;
await client.updateApplicationSettings(settings);
}
public async getIsConsumption(context: IActionContext): Promise<boolean> {
let result: boolean | undefined = this._cachedIsConsumption;
if (result === undefined) {
try {
const client = await this.site.createClient(context);
result = await client.getIsConsumption(context);
} catch {
// ignore and use default
result = true;
}
this._cachedIsConsumption = result;
}
return result;
}
public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise<AzExtTreeItem[]> {
const client = await this.site.createClient(context);
const siteConfig: SiteConfig = await client.getSiteConfig();
const sourceControl: SiteSourceControl = await client.getSourceControl();
const proxyTree: SlotTreeItem = this as unknown as SlotTreeItem;
this.deploymentsNode = new DeploymentsTreeItem(proxyTree, {
site: this.site,
siteConfig,
sourceControl,
contextValuesToAdd: ['azFunc']
});
this.appSettingsTreeItem = new AppSettingsTreeItem(proxyTree, this.site, {
contextValuesToAdd: ['azFunc']
});
this._siteFilesTreeItem = new SiteFilesTreeItem(proxyTree, {
site: this.site,
isReadOnly: true,
contextValuesToAdd: ['azFunc']
});
this._logFilesTreeItem = new LogFilesTreeItem(proxyTree, {
site: this.site,
contextValuesToAdd: ['azFunc']
});
if (!this._functionsTreeItem) {
this._functionsTreeItem = await RemoteFunctionsTreeItem.createFunctionsTreeItem(context, proxyTree);
}
const children: AzExtTreeItem[] = [this._functionsTreeItem, this.appSettingsTreeItem, this._siteFilesTreeItem, this._logFilesTreeItem, this.deploymentsNode];
if (!this.site.isSlot) {
this._slotsTreeItem = new SlotsTreeItem(proxyTree);
children.push(this._slotsTreeItem);
}
return children;
}
// eslint-disable-next-line @typescript-eslint/require-await
public async pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): Promise<AzExtTreeItem | undefined> {
if (!this.site.isSlot) {
for (const expectedContextValue of expectedContextValues) {
switch (expectedContextValue) {
case SlotsTreeItem.contextValue:
case ResolvedFunctionAppResource.slotContextValue:
return this._slotsTreeItem;
default:
}
}
}
for (const expectedContextValue of expectedContextValues) {
if (expectedContextValue instanceof RegExp) {
const appSettingsContextValues = [AppSettingsTreeItem.contextValue, AppSettingTreeItem.contextValue];
if (matchContextValue(expectedContextValue, appSettingsContextValues)) {
return this.appSettingsTreeItem;
}
const deploymentsContextValues = [DeploymentsTreeItem.contextValueConnected, DeploymentsTreeItem.contextValueUnconnected, DeploymentTreeItem.contextValue];
if (matchContextValue(expectedContextValue, deploymentsContextValues)) {
return this.deploymentsNode;
}
if (matchContextValue(expectedContextValue, [ResolvedFunctionAppResource.slotContextValue])) {
return this._slotsTreeItem;
}
}
if (typeof expectedContextValue === 'string') {
// DeploymentTreeItem.contextValue is a RegExp, but the passed in contextValue can be a string so check for a match
if (DeploymentTreeItem.contextValue.test(expectedContextValue)) {
return this.deploymentsNode;
}
} else if (matchesAnyPart(expectedContextValue, ProjectResource.Functions, ProjectResource.Function)) {
return this._functionsTreeItem;
}
}
return undefined;
}
public compareChildrenImpl(): number {
return 0; // already sorted
}
public async isReadOnly(context: IActionContext): Promise<boolean> {
const client = await this.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
return [runFromPackageKey, 'WEBSITE_RUN_FROM_ZIP'].some(key => appSettings.properties && envUtils.isEnvironmentVariableSet(appSettings.properties[key]));
}
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
const wizardContext: IDeleteSiteWizardContext = Object.assign(context, {
site: this.site,
...(await createActivityContext())
});
const confirmationMessage = localize('deleteConfirmation', 'Are you sure you want to delete function app "{0}"?', this.site.fullName);
const wizard = new AzureWizard(wizardContext, {
title: localize('deleteSwa', 'Delete Function App "{0}"', this.label),
promptSteps: [new DeleteConfirmationStep(confirmationMessage), new DeleteLastServicePlanStep()],
executeSteps: [new DeleteSiteStep()]
});
await wizard.prompt();
await wizard.execute();
}
}
function matchContextValue(expectedContextValue: RegExp | string, matches: (string | RegExp)[]): boolean {
if (expectedContextValue instanceof RegExp) {
return matches.some((match) => {
if (match instanceof RegExp) {
return expectedContextValue.toString() === match.toString();
}
return expectedContextValue.test(match);
});
} else {
return matches.some((match) => {
if (match instanceof RegExp) {
return match.test(expectedContextValue);
}
return expectedContextValue === match;
});
}
}

Просмотреть файл

@ -3,21 +3,111 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ParsedSite } from '@microsoft/vscode-azext-azureappservice';
import { SlotsTreeItem } from './SlotsTreeItem';
import { SlotTreeItemBase } from './SlotTreeItemBase';
import { AppSettingsTreeItem, DeploymentsTreeItem, ParsedSite } from '@microsoft/vscode-azext-azureappservice';
import { AzExtParentTreeItem, AzExtTreeItem, IActionContext } from '@microsoft/vscode-azext-utils';
import { IParsedHostJson } from '../funcConfig/host';
import { FuncVersion } from '../FuncVersion';
import { treeUtils } from '../utils/treeUtils';
import { ApplicationSettings, FuncHostRequest, IProjectTreeItem } from './IProjectTreeItem';
import { ProjectSource } from './projectContextValues';
import { RemoteFunctionTreeItem } from './remoteProject/RemoteFunctionTreeItem';
import { ResolvedFunctionAppResource } from './ResolvedFunctionAppResource';
export class SlotTreeItem extends SlotTreeItemBase {
public static contextValue: string = 'azFuncSlot';
public readonly contextValue: string = SlotTreeItem.contextValue;
public readonly parent: SlotsTreeItem;
export function isSlotTreeItem(treeItem: SlotTreeItem | RemoteFunctionTreeItem | AzExtParentTreeItem): treeItem is SlotTreeItem {
return !!(treeItem as SlotTreeItem).site;
}
public constructor(parent: SlotsTreeItem, site: ParsedSite) {
super(parent, site);
export class SlotTreeItem extends AzExtParentTreeItem implements IProjectTreeItem {
public logStreamPath: string = '';
public readonly appSettingsTreeItem: AppSettingsTreeItem;
public deploymentsNode: DeploymentsTreeItem | undefined;
public readonly source: ProjectSource = ProjectSource.Remote;
public site: ParsedSite;
public readonly contextValue: string;
public resolved: ResolvedFunctionAppResource;
public constructor(parent: AzExtParentTreeItem, resolvedFunctionAppResource: ResolvedFunctionAppResource) {
super(parent);
this.resolved = resolvedFunctionAppResource;
// this is for the slotContextValue because it never gets resolved by the Resources extension
const slotContextValue = this.resolved.site.isSlot ? ResolvedFunctionAppResource.slotContextValue : ResolvedFunctionAppResource.productionContextValue;
const contextValues = [slotContextValue, 'slot'];
this.contextValue = Array.from(new Set(contextValues)).sort().join(';');
this.site = this.resolved.site;
this.iconPath = treeUtils.getIconPath(slotContextValue);
}
public get label(): string {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.site.slotName!;
return this.resolved.label;
}
public get logStreamLabel(): string {
return this.resolved.logStreamLabel;
}
public get id(): string {
return this.resolved.id;
}
public async getHostRequest(): Promise<FuncHostRequest> {
return await this.resolved.getHostRequest();
}
public get description(): string | undefined {
return this.resolved.description;
}
public hasMoreChildrenImpl(): boolean {
return this.resolved.hasMoreChildrenImpl();
}
/**
* NOTE: We need to be extra careful in this method because it blocks many core scenarios (e.g. deploy) if the tree item is listed as invalid
*/
public async refreshImpl(context: IActionContext): Promise<void> {
return await this.resolved.refreshImpl(context);
}
public async getVersion(context: IActionContext): Promise<FuncVersion> {
return await this.resolved.getVersion(context);
}
public async getHostJson(context: IActionContext): Promise<IParsedHostJson> {
return await this.resolved.getHostJson(context);
}
public async getApplicationSettings(context: IActionContext): Promise<ApplicationSettings> {
return await this.resolved.getApplicationSettings(context);
}
public async setApplicationSetting(context: IActionContext, key: string, value: string): Promise<void> {
return await this.resolved.setApplicationSetting(context, key, value);
}
public async getIsConsumption(context: IActionContext): Promise<boolean> {
return await this.resolved.getIsConsumption(context);
}
public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise<AzExtTreeItem[]> {
return await this.resolved.loadMoreChildrenImpl.call(this, _clearCache, context) as AzExtTreeItem[];
}
// eslint-disable-next-line @typescript-eslint/require-await
public async pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): Promise<AzExtTreeItem | undefined> {
return await this.resolved.pickTreeItemImpl(expectedContextValues);
}
public compareChildrenImpl(): number {
return this.resolved.compareChildrenImpl();
}
public async isReadOnly(context: IActionContext): Promise<boolean> {
return await this.resolved.isReadOnly(context);
}
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
await this.resolved.deleteTreeItemImpl(context);
}
}

Просмотреть файл

@ -1,217 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SiteConfig, SiteSourceControl, StringDictionary } from '@azure/arm-appservice';
import { AppSettingsTreeItem, AppSettingTreeItem, deleteSite, DeploymentsTreeItem, DeploymentTreeItem, getFile, LogFilesTreeItem, ParsedSite, SiteFilesTreeItem } from '@microsoft/vscode-azext-azureappservice';
import { AzExtParentTreeItem, AzExtTreeItem, IActionContext, TreeItemIconPath } from '@microsoft/vscode-azext-utils';
import { runFromPackageKey } from '../constants';
import { IParsedHostJson, parseHostJson } from '../funcConfig/host';
import { FuncVersion, latestGAVersion, tryParseFuncVersion } from '../FuncVersion';
import { envUtils } from '../utils/envUtils';
import { nonNullValue } from '../utils/nonNull';
import { treeUtils } from '../utils/treeUtils';
import { ApplicationSettings, FuncHostRequest, IProjectTreeItem } from './IProjectTreeItem';
import { matchesAnyPart, ProjectResource, ProjectSource } from './projectContextValues';
import { RemoteFunctionsTreeItem } from './remoteProject/RemoteFunctionsTreeItem';
export abstract class SlotTreeItemBase extends AzExtParentTreeItem implements IProjectTreeItem {
public logStreamPath: string = '';
public readonly appSettingsTreeItem: AppSettingsTreeItem;
public deploymentsNode: DeploymentsTreeItem | undefined;
public readonly source: ProjectSource = ProjectSource.Remote;
public site: ParsedSite;
public abstract readonly contextValue: string;
public abstract readonly label: string;
private _functionsTreeItem: RemoteFunctionsTreeItem | undefined;
private readonly _logFilesTreeItem: LogFilesTreeItem;
private readonly _siteFilesTreeItem: SiteFilesTreeItem;
private _cachedVersion: FuncVersion | undefined;
private _cachedHostJson: IParsedHostJson | undefined;
private _cachedIsConsumption: boolean | undefined;
public constructor(parent: AzExtParentTreeItem, site: ParsedSite) {
super(parent);
this.site = site;
this.appSettingsTreeItem = new AppSettingsTreeItem(this, site);
this._siteFilesTreeItem = new SiteFilesTreeItem(this, site, true);
this._logFilesTreeItem = new LogFilesTreeItem(this, site);
const valuesToMask = [
site.siteName, site.slotName, site.defaultHostName, site.resourceGroup,
site.planName, site.planResourceGroup, site.kuduHostName, site.gitUrl,
site.rawSite.repositorySiteName, ...(site.rawSite.hostNames || []), ...(site.rawSite.enabledHostNames || [])
];
for (const v of valuesToMask) {
if (v) {
this.valuesToMask.push(v);
}
}
}
public get logStreamLabel(): string {
return this.site.fullName;
}
public get id(): string {
return this.site.id;
}
public async getHostRequest(): Promise<FuncHostRequest> {
return { url: this.site.defaultHostUrl };
}
public get description(): string | undefined {
return this._state?.toLowerCase() !== 'running' ? this._state : undefined;
}
public get iconPath(): TreeItemIconPath {
return treeUtils.getIconPath(this.contextValue);
}
private get _state(): string | undefined {
return this.site.rawSite.state;
}
public hasMoreChildrenImpl(): boolean {
return false;
}
/**
* NOTE: We need to be extra careful in this method because it blocks many core scenarios (e.g. deploy) if the tree item is listed as invalid
*/
public async refreshImpl(context: IActionContext): Promise<void> {
this._cachedVersion = undefined;
this._cachedHostJson = undefined;
this._cachedIsConsumption = undefined;
const client = await this.site.createClient(context);
this.site = new ParsedSite(nonNullValue(await client.getSite(), 'site'), this.subscription);
}
public async getVersion(context: IActionContext): Promise<FuncVersion> {
let result: FuncVersion | undefined = this._cachedVersion;
if (result === undefined) {
let version: FuncVersion | undefined;
try {
const client = await this.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
version = tryParseFuncVersion(appSettings.properties && appSettings.properties.FUNCTIONS_EXTENSION_VERSION);
} catch {
// ignore and use default
}
result = version || latestGAVersion;
this._cachedVersion = result;
}
return result;
}
public async getHostJson(context: IActionContext): Promise<IParsedHostJson> {
let result: IParsedHostJson | undefined = this._cachedHostJson;
if (!result) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let data: any;
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
data = JSON.parse((await getFile(context, this.site, 'site/wwwroot/host.json')).data);
} catch {
// ignore and use default
}
const version: FuncVersion = await this.getVersion(context);
result = parseHostJson(data, version);
this._cachedHostJson = result;
}
return result;
}
public async getApplicationSettings(context: IActionContext): Promise<ApplicationSettings> {
const client = await this.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
return appSettings.properties || {};
}
public async setApplicationSetting(context: IActionContext, key: string, value: string): Promise<void> {
const client = await this.site.createClient(context);
const settings: StringDictionary = await client.listApplicationSettings();
if (!settings.properties) {
settings.properties = {};
}
settings.properties[key] = value;
await client.updateApplicationSettings(settings);
}
public async getIsConsumption(context: IActionContext): Promise<boolean> {
let result: boolean | undefined = this._cachedIsConsumption;
if (result === undefined) {
try {
const client = await this.site.createClient(context);
result = await client.getIsConsumption(context);
} catch {
// ignore and use default
result = true;
}
this._cachedIsConsumption = result;
}
return result;
}
public async loadMoreChildrenImpl(_clearCache: boolean, context: IActionContext): Promise<AzExtTreeItem[]> {
const client = await this.site.createClient(context);
const siteConfig: SiteConfig = await client.getSiteConfig();
const sourceControl: SiteSourceControl = await client.getSourceControl();
this.deploymentsNode = new DeploymentsTreeItem(this, this.site, siteConfig, sourceControl);
if (!this._functionsTreeItem) {
this._functionsTreeItem = await RemoteFunctionsTreeItem.createFunctionsTreeItem(context, this);
}
return [this._functionsTreeItem, this.appSettingsTreeItem, this._siteFilesTreeItem, this._logFilesTreeItem, this.deploymentsNode];
}
// eslint-disable-next-line @typescript-eslint/require-await
public async pickTreeItemImpl(expectedContextValues: (string | RegExp)[]): Promise<AzExtTreeItem | undefined> {
for (const expectedContextValue of expectedContextValues) {
switch (expectedContextValue) {
case AppSettingsTreeItem.contextValue:
case AppSettingTreeItem.contextValue:
return this.appSettingsTreeItem;
case DeploymentsTreeItem.contextValueConnected:
case DeploymentsTreeItem.contextValueUnconnected:
case DeploymentTreeItem.contextValue:
return this.deploymentsNode;
default:
if (typeof expectedContextValue === 'string') {
// DeploymentTreeItem.contextValue is a RegExp, but the passed in contextValue can be a string so check for a match
if (DeploymentTreeItem.contextValue.test(expectedContextValue)) {
return this.deploymentsNode;
}
} else if (matchesAnyPart(expectedContextValue, ProjectResource.Functions, ProjectResource.Function)) {
return this._functionsTreeItem;
}
}
}
return undefined;
}
public compareChildrenImpl(): number {
return 0; // already sorted
}
public async isReadOnly(context: IActionContext): Promise<boolean> {
const client = await this.site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
return [runFromPackageKey, 'WEBSITE_RUN_FROM_ZIP'].some(key => appSettings.properties && envUtils.isEnvironmentVariableSet(appSettings.properties[key]));
}
public async deleteTreeItemImpl(context: IActionContext): Promise<void> {
await deleteSite(context, this.site);
}
}

Просмотреть файл

@ -11,7 +11,7 @@ import { showSiteCreated } from '../commands/createFunctionApp/showSiteCreated';
import { localize } from '../localize';
import { createWebSiteClient } from '../utils/azureClients';
import { treeUtils } from '../utils/treeUtils';
import { ProductionSlotTreeItem } from './ProductionSlotTreeItem';
import { ResolvedFunctionAppResource } from './ResolvedFunctionAppResource';
import { SlotTreeItem } from './SlotTreeItem';
export class SlotsTreeItem extends AzExtParentTreeItem {
@ -19,12 +19,12 @@ export class SlotsTreeItem extends AzExtParentTreeItem {
public readonly contextValue: string = SlotsTreeItem.contextValue;
public readonly label: string = localize('slots', 'Slots');
public readonly childTypeLabel: string = localize('slot', 'Slot');
public readonly parent: ProductionSlotTreeItem;
public readonly parent: SlotTreeItem;
public suppressMaskLabel: boolean = true;
private _nextLink: string | undefined;
public constructor(parent: ProductionSlotTreeItem) {
public constructor(parent: SlotTreeItem) {
super(parent);
}
@ -45,7 +45,7 @@ export class SlotsTreeItem extends AzExtParentTreeItem {
this._nextLink = undefined;
}
const client: WebSiteManagementClient = await createWebSiteClient([context, this]);
const client: WebSiteManagementClient = await createWebSiteClient([context, this.subscription]);
// https://github.com/Azure/azure-sdk-for-js/issues/20380
const webAppCollection: Site[] = await uiUtils.listAllIterator(client.webApps.listSlots(this.parent.site.resourceGroup, this.parent.site.siteName));
@ -53,7 +53,7 @@ export class SlotsTreeItem extends AzExtParentTreeItem {
webAppCollection,
'azFuncInvalidSlot',
(site: Site) => {
return new SlotTreeItem(this, new ParsedSite(site, this.subscription));
return new SlotTreeItem(this, new ResolvedFunctionAppResource(this.subscription, site));
},
(site: Site) => {
return site.name;
@ -66,6 +66,6 @@ export class SlotsTreeItem extends AzExtParentTreeItem {
const newSite: Site = await createSlot(this.parent.site, existingSlots.map(s => s.site), context);
const parsedSite = new ParsedSite(newSite, this.subscription);
showSiteCreated(parsedSite, context);
return new SlotTreeItem(this, parsedSite);
return new SlotTreeItem(this, new ResolvedFunctionAppResource(this.subscription, newSite));
}
}

Просмотреть файл

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Site, WebSiteManagementClient } from '@azure/arm-appservice';
import { AppInsightsCreateStep, AppInsightsListStep, AppKind, AppServicePlanCreateStep, CustomLocationListStep, IAppServiceWizardContext, ParsedSite, SiteNameStep, WebsiteOS } from '@microsoft/vscode-azext-azureappservice';
import { AppInsightsCreateStep, AppInsightsListStep, AppKind, AppServicePlanCreateStep, CustomLocationListStep, IAppServiceWizardContext, SiteNameStep, WebsiteOS } from '@microsoft/vscode-azext-azureappservice';
import { INewStorageAccountDefaults, LocationListStep, ResourceGroupCreateStep, ResourceGroupListStep, StorageAccountCreateStep, StorageAccountKind, StorageAccountListStep, StorageAccountPerformance, StorageAccountReplication, SubscriptionTreeItemBase, uiUtils, VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils';
import { AzExtTreeItem, AzureWizard, AzureWizardExecuteStep, AzureWizardPromptStep, IActionContext, ICreateChildImplContext, parseError } from '@microsoft/vscode-azext-utils';
import { WorkspaceFolder } from 'vscode';
@ -13,14 +13,17 @@ import { FunctionAppHostingPlanStep, setConsumptionPlanProperties } from '../com
import { IFunctionAppWizardContext } from '../commands/createFunctionApp/IFunctionAppWizardContext';
import { FunctionAppStackStep } from '../commands/createFunctionApp/stacks/FunctionAppStackStep';
import { funcVersionSetting, projectLanguageSetting, webProvider } from '../constants';
import { ext } from '../extensionVariables';
import { tryGetLocalFuncVersion } from '../funcCoreTools/tryGetLocalFuncVersion';
import { FuncVersion, latestGAVersion, tryParseFuncVersion } from '../FuncVersion';
import { localize } from "../localize";
import { createActivityContext } from '../utils/activityUtils';
import { createWebSiteClient } from '../utils/azureClients';
import { nonNullProp } from '../utils/nonNull';
import { getRootFunctionsWorkerRuntime, getWorkspaceSetting, getWorkspaceSettingFromAnyFolder } from '../vsCodeConfig/settings';
import { ProductionSlotTreeItem } from './ProductionSlotTreeItem';
import { isProjectCV, isRemoteProjectCV } from './projectContextValues';
import { ResolvedFunctionAppResource } from './ResolvedFunctionAppResource';
import { SlotTreeItem } from './SlotTreeItem';
export interface ICreateFunctionAppContext extends ICreateChildImplContext {
newResourceGroupName?: string;
@ -43,7 +46,7 @@ export class SubscriptionTreeItem extends SubscriptionTreeItemBase {
}
// Load more currently broken https://github.com/Azure/azure-sdk-for-js/issues/20380
const client: WebSiteManagementClient = await createWebSiteClient([context, this]);
const client: WebSiteManagementClient = await createWebSiteClient([context, this.subscription]);
let webAppCollection: Site[];
try {
webAppCollection = await uiUtils.listAllIterator(client.webApps.list());
@ -62,9 +65,9 @@ export class SubscriptionTreeItem extends SubscriptionTreeItemBase {
webAppCollection,
'azFuncInvalidFunctionApp',
(site: Site) => {
const parsedSite = new ParsedSite(site, this.subscription);
if (parsedSite.isFunctionApp) {
return new ProductionSlotTreeItem(this, parsedSite);
const resolved = new ResolvedFunctionAppResource(this.subscription, site);
if (resolved.site.isFunctionApp) {
return new SlotTreeItem(this, resolved);
}
return undefined;
},
@ -74,17 +77,18 @@ export class SubscriptionTreeItem extends SubscriptionTreeItemBase {
);
}
public async createChildImpl(context: ICreateFunctionAppContext): Promise<AzExtTreeItem> {
public static async createChild(context: ICreateFunctionAppContext, subscription: SubscriptionTreeItem): Promise<SlotTreeItem> {
const version: FuncVersion = await getDefaultFuncVersion(context);
context.telemetry.properties.projectRuntime = version;
const language: string | undefined = context.workspaceFolder ? getWorkspaceSetting(projectLanguageSetting, context.workspaceFolder) : getWorkspaceSettingFromAnyFolder(projectLanguageSetting);
context.telemetry.properties.projectLanguage = language;
const wizardContext: IFunctionAppWizardContext = Object.assign(context, this.subscription, {
const wizardContext: IFunctionAppWizardContext = Object.assign(context, subscription.subscription, {
newSiteKind: AppKind.functionapp,
resourceGroupDeferLocationStep: true,
version,
language
language,
...(await createActivityContext())
});
const promptSteps: AzureWizardPromptStep<IAppServiceWizardContext>[] = [];
@ -141,7 +145,6 @@ export class SubscriptionTreeItem extends SubscriptionTreeItemBase {
const wizard: AzureWizard<IAppServiceWizardContext> = new AzureWizard(wizardContext, { promptSteps, executeSteps, title });
await wizard.prompt();
context.showCreatingTreeItem(nonNullProp(wizardContext, 'newSiteName'));
if (!context.advancedCreation) {
const newName: string | undefined = await wizardContext.relatedNameTask;
if (!newName) {
@ -153,9 +156,12 @@ export class SubscriptionTreeItem extends SubscriptionTreeItemBase {
wizardContext.newAppInsightsName = newName;
}
wizardContext.activityTitle = localize('functionAppCreateActivityTitle', 'Create Function App "{0}"', nonNullProp(wizardContext, 'newSiteName'))
await wizard.execute();
return new ProductionSlotTreeItem(this, new ParsedSite(nonNullProp(wizardContext, 'site'), this.subscription));
const resolved = new ResolvedFunctionAppResource(subscription.subscription, nonNullProp(wizardContext, 'site'));
await ext.rgApi.tree.refresh(context);
return new SlotTreeItem(subscription, resolved);
}
public isAncestorOfImpl(contextValue: string | RegExp): boolean {

Просмотреть файл

@ -9,20 +9,20 @@ import { isArray } from 'util';
import { localize } from '../../localize';
import { delay } from '../../utils/delay';
import { FunctionsTreeItemBase } from '../FunctionsTreeItemBase';
import { SlotTreeItemBase } from '../SlotTreeItemBase';
import { SlotTreeItem } from '../SlotTreeItem';
import { getFunctionNameFromId, RemoteFunctionTreeItem } from './RemoteFunctionTreeItem';
export class RemoteFunctionsTreeItem extends FunctionsTreeItemBase {
public readonly parent: SlotTreeItemBase;
public readonly parent: SlotTreeItem;
public isReadOnly: boolean;
private _nextLink: string | undefined;
private constructor(parent: SlotTreeItemBase) {
private constructor(parent: SlotTreeItem) {
super(parent);
}
public static async createFunctionsTreeItem(context: IActionContext, parent: SlotTreeItemBase): Promise<RemoteFunctionsTreeItem> {
public static async createFunctionsTreeItem(context: IActionContext, parent: SlotTreeItem): Promise<RemoteFunctionsTreeItem> {
const ti: RemoteFunctionsTreeItem = new RemoteFunctionsTreeItem(parent);
// initialize
await ti.refreshImpl(context);

Просмотреть файл

@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils";
import { ext } from "../extensionVariables";
import { getWorkspaceSetting } from "../vsCodeConfig/settings";
export async function createActivityContext(): Promise<ExecuteActivityContext> {
return {
registerActivity: async (activity) => ext.rgApi.registerActivity(activity),
suppressNotification: await getWorkspaceSetting('suppressActivityNotifications', undefined, 'azureResourceGroups'),
};
}

Просмотреть файл

@ -51,7 +51,7 @@ suite('Add Binding', () => {
});
test('Tree', async () => {
const treeItem: AzExtTreeItem | undefined = await ext.tree.findTreeItem(`/localProject0/functions/${functionName}`, await createTestActionContext());
const treeItem: AzExtTreeItem | undefined = await ext.rgApi.tree.findTreeItem(`/localProject0/functions/${functionName}`, await createTestActionContext());
assert.ok(treeItem, 'Failed to find tree item');
await validateAddBinding(treeItem, []);
});

Просмотреть файл

@ -7,7 +7,7 @@ import { runWithInputs } from '@microsoft/vscode-azext-dev';
import { AzureExtensionApiProvider } from "@microsoft/vscode-azext-utils/api";
import * as path from 'path';
import { Extension, extensions } from "vscode";
import { nonNullValue, ProjectLanguage, registerOnActionStartHandler } from '../extension.bundle';
import { extensionId, nonNullValue, ProjectLanguage, registerOnActionStartHandler } from '../extension.bundle';
// eslint-disable-next-line no-restricted-imports
import { AzureFunctionsExtensionApi } from '../src/vscode-azurefunctions.api';
import { getTestWorkspaceFolder, testFolderPath } from './global.test';
@ -17,7 +17,7 @@ suite(`AzureFunctionsExtensionApi`, () => {
let api: AzureFunctionsExtensionApi;
suiteSetup(() => {
const extension: Extension<AzureExtensionApiProvider> | undefined = extensions.getExtension('ms-azuretools.vscode-azurefunctions');
const extension: Extension<AzureExtensionApiProvider> | undefined = extensions.getExtension(extensionId);
api = nonNullValue(extension).exports.getApi<AzureFunctionsExtensionApi>('^1.0.0');
});

Просмотреть файл

@ -7,7 +7,7 @@ import { WebSiteManagementClient } from '@azure/arm-appservice';
import { ResourceManagementClient } from '@azure/arm-resources';
import { createTestActionContext, TestAzureAccount } from '@microsoft/vscode-azext-dev';
import * as vscode from 'vscode';
import { AzExtTreeDataProvider, AzureAccountTreeItemWithProjects, createAzureClient, ext } from '../../extension.bundle';
import { AzureAccountTreeItemWithProjects, createAzureClient, ext } from '../../extension.bundle';
import { longRunningTestsEnabled } from '../global.test';
export let testAccount: TestAzureAccount;
@ -22,7 +22,6 @@ suiteSetup(async function (this: Mocha.Context): Promise<void> {
testAccount = new TestAzureAccount(vscode);
await testAccount.signIn();
ext.azureAccountTreeItem = new AzureAccountTreeItemWithProjects(testAccount);
ext.tree = new AzExtTreeDataProvider(ext.azureAccountTreeItem, 'azureFunctions.loadMore');
testClient = createAzureClient([await createTestActionContext(), testAccount.getSubscriptionContext()], WebSiteManagementClient);
}
});

Просмотреть файл

@ -7,7 +7,7 @@ import * as assert from 'assert';
import * as fse from 'fs-extra';
import * as globby from 'globby';
import * as path from 'path';
import { FuncVersion, getContainingWorkspace, IExtensionsJson, ILaunchJson, ITasksJson, JavaBuildTool, ProjectLanguage } from '../../extension.bundle';
import { extensionId, FuncVersion, getContainingWorkspace, IExtensionsJson, ILaunchJson, ITasksJson, JavaBuildTool, ProjectLanguage } from '../../extension.bundle';
export const defaultTestFuncVersion: FuncVersion = FuncVersion.v3;
@ -337,7 +337,7 @@ export async function validateProject(projectPath: string, options: IValidatePro
//
// Validate extensions.json
//
const recs: string[] = options.expectedExtensionRecs.concat('ms-azuretools.vscode-azurefunctions');
const recs: string[] = options.expectedExtensionRecs.concat(extensionId);
const extensionsJson: IExtensionsJson = <IExtensionsJson>await fse.readJSON(path.join(rootPath, '.vscode', 'extensions.json'));
extensionsJson.recommendations = extensionsJson.recommendations || [];
assert.equal(extensionsJson.recommendations.length, recs.length, "extensions.json doesn't have the expected number of recommendations.");