diff --git a/package-lock.json b/package-lock.json index f57574cb0..e2352786d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,9 @@ "version": "0.12.3-alpha.0", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { - "@azure/arm-appservice": "^11.0.0", + "@azure/arm-appservice": "^15.0.0", "@azure/arm-resources": "^5.0.0", + "@azure/identity": "^4.3.0", "@microsoft/vscode-azext-azureappsettings": "^0.2.0", "@microsoft/vscode-azext-azureutils": "^2.0.0", "@microsoft/vscode-azext-utils": "^2.0.0", @@ -78,20 +79,20 @@ } }, "node_modules/@azure/arm-appservice": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@azure/arm-appservice/-/arm-appservice-11.0.0.tgz", - "integrity": "sha512-y+GllRQNlXqVR8tzzZGdzb/J+EtvIBcFD0dXSngaBkvl5+wgt+/wclJSx2xcSVZQO+yEj9YE/xG4EXkr/qb23g==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@azure/arm-appservice/-/arm-appservice-15.0.0.tgz", + "integrity": "sha512-huJ2uFDXB7w0cYKqxhzYOHuTsuLCY1e0xmWFF8G3KpDbQGnFDM3AVNtxWPas50OxuSWClblqSaExiS/XnWhTTg==", "dependencies": { "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.0.0", - "@azure/core-lro": "^2.2.0", + "@azure/core-auth": "^1.6.0", + "@azure/core-client": "^1.7.0", + "@azure/core-lro": "^2.5.4", "@azure/core-paging": "^1.2.0", - "@azure/core-rest-pipeline": "^1.1.0", + "@azure/core-rest-pipeline": "^1.14.0", "tslib": "^2.2.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/arm-resources": { @@ -178,40 +179,64 @@ } }, "node_modules/@azure/core-auth": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.4.0.tgz", - "integrity": "sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.7.2.tgz", + "integrity": "sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g==", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "tslib": "^2.2.0" + "@azure/abort-controller": "^2.0.0", + "@azure/core-util": "^1.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-client": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.7.2.tgz", - "integrity": "sha512-ye5554gnVnXdfZ64hptUtETgacXoRWxYv1JF5MctoAzTSH5dXhDPZd9gOjDPyWMcLIk58pnP5+p5vGX6PYn1ag==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz", + "integrity": "sha512-kRdry/rav3fUKHl/aDLd/pDLcB+4pOFwPPTVEExuMyaI5r+JBbMWqRbCY1pn5BniDaU3lRxO9eaQ1AmSMehl/w==", "dependencies": { - "@azure/abort-controller": "^1.0.0", + "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-rest-pipeline": "^1.9.1", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.6.1", "@azure/logger": "^1.0.0", - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, "node_modules/@azure/core-lro": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.1.tgz", - "integrity": "sha512-JHQy/bA3NOz2WuzOi5zEk6n/TJdAropupxUT521JIJvW7EXV2YN2SFYZrf/2RHeD28QAClGdynYadZsbmP+nyQ==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", + "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", "dependencies": { "@azure/abort-controller": "^1.0.0", + "@azure/core-util": "^1.2.0", "@azure/logger": "^1.0.0", "tslib": "^2.2.0" }, @@ -231,23 +256,55 @@ } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.2.tgz", - "integrity": "sha512-e3WzAsRKLor5EgK2bQqR1OY5D7VBqzORHtlqtygZZQGCYOIBsynqrZBa8MFD1Ue9r8TPtofOLditalnlQHS45Q==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.16.1.tgz", + "integrity": "sha512-ExPSbgjwCoht6kB7B4MeZoBAxcQSIl29r/bPeazZJx50ej4JJCByimLOrZoIsurISNyJQQHf30b3JfqC3Hb88A==", "dependencies": { - "@azure/abort-controller": "^1.0.0", + "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.4.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.9.0", "@azure/logger": "^1.0.0", - "form-data": "^4.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "tslib": "^2.2.0", - "uuid": "^8.3.0" + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" } }, "node_modules/@azure/core-tracing": { @@ -262,15 +319,50 @@ } }, "node_modules/@azure/core-util": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.2.0.tgz", - "integrity": "sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.9.0.tgz", + "integrity": "sha512-AfalUQ1ZppaKuxPPMsFEUdX6GZPB3d9paR9d/TTL7Ow2De8cJaC7ibi7kWVlFAVPCYo31OcnGymc0R89DX8Oaw==", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.3.0.tgz", + "integrity": "sha512-LHZ58/RsIpIWa4hrrE2YuJ/vzG1Jv9f774RfTTAVDZDriubvJ0/S5u4pnw4akJDlS0TiJb6VMphmVUFsWmgodQ==", "dependencies": { "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.5.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.1.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.3.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^3.11.1", + "@azure/msal-node": "^2.9.2", + "events": "^3.0.0", + "jws": "^4.0.0", + "open": "^8.0.0", + "stoppable": "^1.1.0", "tslib": "^2.2.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/logger": { @@ -290,6 +382,38 @@ "integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw==", "peer": true }, + "node_modules/@azure/msal-browser": { + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.18.0.tgz", + "integrity": "sha512-jvK5bDUWbpOaJt2Io/rjcaOVcUzkqkrCme/WntdV1SMUc67AiTcEdKuY6G/nMQ7N5Cfsk9SfpugflQwDku53yg==", + "dependencies": { + "@azure/msal-common": "14.13.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "14.13.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.13.0.tgz", + "integrity": "sha512-b4M/tqRzJ4jGU91BiwCsLTqChveUEyFK3qY2wGfZ0zBswIBZjAxopx5CYt5wzZFKuN15HqRDYXQbztttuIC3nA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.10.0.tgz", + "integrity": "sha512-JxsSE0464a8IA/+q5EHKmchwNyUFJHtCH00tSXsLaOddwLjG6yVvTH6lGgPcWMhO7YWUXj/XVgVgeE9kZtsPUQ==", + "dependencies": { + "@azure/msal-common": "14.13.0", + "jsonwebtoken": "^9.0.0", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -886,14 +1010,6 @@ "url": "https://ko-fi.com/killymxi" } }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "engines": { - "node": ">= 10" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", @@ -1679,6 +1795,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, "dependencies": { "debug": "4" }, @@ -2417,6 +2534,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3412,6 +3534,14 @@ "node": ">= 0.10" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, "node_modules/define-properties": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", @@ -3682,6 +3812,14 @@ "node": ">=0.10.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/electron-to-chromium": { "version": "1.4.349", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.349.tgz", @@ -4244,7 +4382,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -5877,16 +6014,26 @@ } }, "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "engines": { - "node": ">= 6" + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" } }, "node_modules/https-browserify": { @@ -5899,6 +6046,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -6268,6 +6416,20 @@ "node": ">=0.10.0" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -6605,6 +6767,17 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -6712,6 +6885,46 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jsonwebtoken/node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -6730,6 +6943,25 @@ "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", "dev": true }, + "node_modules/jwa": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", + "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", + "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", + "dependencies": { + "jwa": "^2.0.0", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keytar": { "version": "7.9.0", "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", @@ -6952,12 +7184,47 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -6978,6 +7245,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -8182,6 +8450,22 @@ "wrappy": "1" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -9270,7 +9554,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -9345,12 +9628,9 @@ } }, "node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -9946,6 +10226,15 @@ "node": ">=0.10.0" } }, + "node_modules/stoppable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stoppable/-/stoppable-1.1.0.tgz", + "integrity": "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==", + "engines": { + "node": ">=4", + "npm": ">=6" + } + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -10558,9 +10847,9 @@ } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -11498,7 +11787,8 @@ "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/yaml": { "version": "1.10.2", diff --git a/package.json b/package.json index f4540e5ca..51e461c20 100644 --- a/package.json +++ b/package.json @@ -494,8 +494,9 @@ "webpack-cli": "^4.6.0" }, "dependencies": { - "@azure/arm-appservice": "^11.0.0", + "@azure/arm-appservice": "^15.0.0", "@azure/arm-resources": "^5.0.0", + "@azure/identity": "^4.3.0", "@microsoft/vscode-azext-azureappsettings": "^0.2.0", "@microsoft/vscode-azext-azureutils": "^2.0.0", "@microsoft/vscode-azext-utils": "^2.0.0", diff --git a/src/commands/createStaticWebApp/IStaticWebAppWizardContext.ts b/src/commands/createStaticWebApp/IStaticWebAppWizardContext.ts index d0411771e..50990f2e1 100644 --- a/src/commands/createStaticWebApp/IStaticWebAppWizardContext.ts +++ b/src/commands/createStaticWebApp/IStaticWebAppWizardContext.ts @@ -3,47 +3,62 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { SkuDescription, StaticSiteARMResource, WebSiteManagementClient } from '@azure/arm-appservice'; -import { IResourceGroupWizardContext } from '@microsoft/vscode-azext-azureutils'; -import { ExecuteActivityContext } from '@microsoft/vscode-azext-utils'; -import { Uri } from 'vscode'; -import { IBuildPreset } from '../../buildPresets/IBuildPreset'; -import { Repository } from '../../git'; -import { BranchData, ListOrgsForUserData, OrgForAuthenticatedUserData } from '../../gitHubTypings'; +import { + SkuDescription, + StaticSiteARMResource, + WebSiteManagementClient, +} from "@azure/arm-appservice"; +import { IResourceGroupWizardContext } from "@microsoft/vscode-azext-azureutils"; +import { ExecuteActivityContext } from "@microsoft/vscode-azext-utils"; +import { Uri } from "vscode"; +import { IBuildPreset } from "../../buildPresets/IBuildPreset"; +import { Repository } from "../../git"; +import { + BranchData, + ListOrgsForUserData, + OrgForAuthenticatedUserData, +} from "../../gitHubTypings"; -export interface IStaticWebAppWizardContext extends IResourceGroupWizardContext, ExecuteActivityContext { - advancedCreation?: boolean; - accessToken: string; - client: WebSiteManagementClient; +export interface IStaticWebAppWizardContext + extends IResourceGroupWizardContext, + ExecuteActivityContext { + advancedCreation?: boolean; + accessToken: string; + client: WebSiteManagementClient; - orgData?: OrgForAuthenticatedUserData | ListOrgsForUserData; - branchData?: Partial; - repoHtmlUrl?: string; + orgData?: OrgForAuthenticatedUserData | ListOrgsForUserData; + branchData?: Partial; + repoHtmlUrl?: string; - repo?: Repository; - uri?: Uri; + repo?: Repository; + uri?: Uri; - // Function projects detected via host.json at SWA create time - detectedApiLocations?: string[]; + // Function projects detected via host.json at SWA create time + detectedApiLocations?: string[]; - newStaticWebAppName?: string; + newStaticWebAppName?: string; - newRepoName?: string; - newRepoIsPrivate?: boolean; - newRemoteShortname?: string; + newRepoName?: string; + newRepoIsPrivate?: boolean; + newRemoteShortname?: string; - originExists?: boolean; + originExists?: boolean; - // prefill the input boxes with preset build values; - // projects are too flexible for us to force users to use these values - buildPreset?: IBuildPreset; + // prefill the input boxes with preset build values; + // projects are too flexible for us to force users to use these values + buildPreset?: IBuildPreset; - appLocation?: string; - apiLocation?: string; - outputLocation?: string; + appLocation?: string; + apiLocation?: string; + outputLocation?: string; - sku?: SkuDescription; + sku?: SkuDescription; - // created when the wizard is done executing - staticWebApp?: StaticSiteARMResource; + // created when the wizard is done executing + staticWebApp?: StaticSiteARMResource; + shouldInitLogicApp?: { + backendResourceId: string; + region: string; + name: string; + }; } diff --git a/src/commands/createStaticWebApp/StaticWebAppCreateStep.ts b/src/commands/createStaticWebApp/StaticWebAppCreateStep.ts index 79298572e..984fa7c11 100644 --- a/src/commands/createStaticWebApp/StaticWebAppCreateStep.ts +++ b/src/commands/createStaticWebApp/StaticWebAppCreateStep.ts @@ -3,43 +3,113 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { StaticSiteARMResource } from "@azure/arm-appservice"; +import { + WebSiteManagementClient, + type StaticSiteARMResource, +} from "@azure/arm-appservice"; +import { DefaultAzureCredential } from "@azure/identity"; import { LocationListStep } from "@microsoft/vscode-azext-azureutils"; -import { AzureWizardExecuteStep, nonNullProp, nonNullValueAndProp } from "@microsoft/vscode-azext-utils"; -import { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; -import { Progress } from "vscode"; +import { + AzureWizardExecuteStep, + nonNullProp, + nonNullValueAndProp, +} from "@microsoft/vscode-azext-utils"; +import type { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; +import type { Octokit } from "@octokit/rest"; +import type { Progress } from "vscode"; import { ext } from "../../extensionVariables"; import { localize } from "../../utils/localize"; -import { IStaticWebAppWizardContext } from "./IStaticWebAppWizardContext"; +import { createOctokitClient } from "../github/createOctokitClient"; +import type { IStaticWebAppWizardContext } from "./IStaticWebAppWizardContext"; +const branch_owner = "alain-zhiyanov"; export class StaticWebAppCreateStep extends AzureWizardExecuteStep { - public priority: number = 250; + public priority = 250; + public async execute( + context: IStaticWebAppWizardContext, + progress: Progress<{ + message?: string | undefined; + increment?: number | undefined; + }> + ): Promise { + if (context.shouldInitLogicApp) { + //There was an issue where some fields of context would be lost when SWA called with LA. This is a temporary fix to find the branch data again here because of that. Note this will only work with alain github. + const octokitClient: Octokit = await createOctokitClient(context); + const repo = context.newStaticWebAppName || "def"; + const { data } = await octokitClient.repos.get({ + owner: branch_owner, + repo, + }); + context.repoHtmlUrl = data.html_url; + const { data: branches } = await octokitClient.repos.listBranches({ + owner: branch_owner, + repo, + }); + const defaultBranch = branches.find((branch) => branch.name === "main"); + if (defaultBranch) { + context.branchData = { name: defaultBranch.name }; + } else { + context.branchData = { name: branches[0].name }; + } + } - public async execute(context: IStaticWebAppWizardContext, progress: Progress<{ message?: string | undefined; increment?: number | undefined }>): Promise { - const newName: string = nonNullProp(context, 'newStaticWebAppName'); - const branchData = nonNullProp(context, 'branchData'); - const siteEnvelope: StaticSiteARMResource = { - repositoryUrl: context.repoHtmlUrl, - branch: branchData.name, - repositoryToken: context.accessToken, - // The SDK hasn't updated to reflect the outputLocation property and platform will continue supporting appArtifactLocation, but will update as soon as available - buildProperties: { - appLocation: context.appLocation, - apiLocation: context.apiLocation, - appArtifactLocation: context.outputLocation - }, - sku: context.sku, - location: (await LocationListStep.getLocation(context)).name - }; + //api call to ARM + const newName: string = nonNullProp(context, "newStaticWebAppName"); + const branchData = nonNullProp(context, "branchData"); + const siteEnvelope: StaticSiteARMResource = { + repositoryUrl: context.repoHtmlUrl, + branch: branchData.name, + repositoryToken: context.accessToken, + // The SDK hasn't updated to reflect the outputLocation property and platform will continue supporting appArtifactLocation, but will update as soon as available + buildProperties: { + appLocation: context.appLocation, + apiLocation: context.apiLocation, + appArtifactLocation: context.outputLocation, + }, + sku: context.sku, + location: (await LocationListStep.getLocation(context)).name, + }; + const creatingSwa: string = localize( + "creatingSwa", + 'Creating new static web app "{0}"...', + newName + ); + progress.report({ message: creatingSwa }); + ext.outputChannel.appendLog(creatingSwa); + context.staticWebApp = + await context.client.staticSites.beginCreateOrUpdateStaticSiteAndWait( + nonNullValueAndProp(context.resourceGroup, "name"), + newName, + siteEnvelope + ); + context.activityResult = context.staticWebApp as AppResource; - const creatingSwa: string = localize('creatingSwa', 'Creating new static web app "{0}"...', newName); - progress.report({ message: creatingSwa }); - ext.outputChannel.appendLog(creatingSwa); - context.staticWebApp = await context.client.staticSites.beginCreateOrUpdateStaticSiteAndWait(nonNullValueAndProp(context.resourceGroup, 'name'), newName, siteEnvelope); - context.activityResult = context.staticWebApp as AppResource; - } + if (context.shouldInitLogicApp) { + const staticSiteLinkedBackendEnvelope = { + backendResourceId: context.shouldInitLogicApp.backendResourceId, + region: context.shouldInitLogicApp.region, + }; + const credential = new DefaultAzureCredential(); + const client = new WebSiteManagementClient( + credential, + context.subscriptionId + ); - public shouldExecute(_wizardContext: IStaticWebAppWizardContext): boolean { - return true; + try { + const result = await client.staticSites.beginLinkBackendAndWait( + nonNullValueAndProp(context.resourceGroup, "name"), + nonNullValueAndProp(context.staticWebApp, "name"), + context.shouldInitLogicApp.name, + staticSiteLinkedBackendEnvelope + ); + console.log(result); + } catch (error) { + console.log(error); + } } + } + + public shouldExecute(_wizardContext: IStaticWebAppWizardContext): boolean { + return true; + } } diff --git a/src/commands/createStaticWebApp/createStaticWebApp.ts b/src/commands/createStaticWebApp/createStaticWebApp.ts index b0888de07..d09969ed8 100644 --- a/src/commands/createStaticWebApp/createStaticWebApp.ts +++ b/src/commands/createStaticWebApp/createStaticWebApp.ts @@ -3,201 +3,556 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { StaticSiteARMResource, WebSiteManagementClient } from '@azure/arm-appservice'; -import { LocationListStep, ResourceGroupCreateStep, ResourceGroupListStep, SubscriptionTreeItemBase, VerifyProvidersStep } from '@microsoft/vscode-azext-azureutils'; -import { AzExtFsExtra, AzureWizard, AzureWizardExecuteStep, AzureWizardPromptStep, ExecuteActivityContext, IActionContext, ICreateChildImplContext, nonNullProp } from '@microsoft/vscode-azext-utils'; -import { AppResource } from '@microsoft/vscode-azext-utils/hostapi'; -import { ProgressLocation, ProgressOptions, Uri, window, workspace } from 'vscode'; -import { Utils } from 'vscode-uri'; -import { StaticWebAppResolver } from '../../StaticWebAppResolver'; -import { DetectorResults, NodeDetector } from '../../detectors/node/NodeDetector'; -import { NodeConstants } from '../../detectors/node/nodeConstants'; -import { VerifyingWorkspaceError } from '../../errors'; -import { ext } from '../../extensionVariables'; -import { createActivityContext } from '../../utils/activityUtils'; -import { createWebSiteClient } from '../../utils/azureClients'; -import { getGitHubAccessToken } from '../../utils/gitHubUtils'; -import { gitPull } from '../../utils/gitUtils'; -import { localize } from '../../utils/localize'; -import { telemetryUtils } from '../../utils/telemetryUtils'; -import { getSingleRootFsPath, getSubFolders, showNoWorkspacePrompt, tryGetWorkspaceFolder } from '../../utils/workspaceUtils'; -import { RemoteShortnameStep } from '../createRepo/RemoteShortnameStep'; -import { RepoCreateStep } from '../createRepo/RepoCreateStep'; -import { RepoNameStep } from '../createRepo/RepoNameStep'; -import { RepoPrivacyStep } from '../createRepo/RepoPrivacyStep'; -import { showSwaCreated } from '../showSwaCreated'; -import { ApiLocationStep } from './ApiLocationStep'; -import { AppLocationStep } from './AppLocationStep'; -import { BuildPresetListStep } from './BuildPresetListStep'; -import { GitHubOrgListStep } from './GitHubOrgListStep'; -import { IStaticWebAppWizardContext } from './IStaticWebAppWizardContext'; -import { OutputLocationStep } from './OutputLocationStep'; -import { SkuListStep } from './SkuListStep'; -import { StaticWebAppCreateStep } from './StaticWebAppCreateStep'; -import { StaticWebAppNameStep } from './StaticWebAppNameStep'; -import { setGitWorkspaceContexts } from './setWorkspaceContexts'; -import { tryGetApiLocations } from './tryGetApiLocations'; - -function isSubscription(item?: SubscriptionTreeItemBase): item is SubscriptionTreeItemBase { - try { - // Accessing item.subscription throws an error for some workspace items - // see https://github.com/microsoft/vscode-azurefunctions/issues/3731 - return !!item && !!item.subscription; - } catch { - return false; - } +// biome-ignore lint/style/useNodejsImportProtocol: +import { promises as fs } from "fs"; // Import the promises API from fs +// biome-ignore lint/style/useNodejsImportProtocol: +import type { + StaticSiteARMResource, + WebSiteManagementClient, +} from "@azure/arm-appservice"; +import { + LocationListStep, + ResourceGroupCreateStep, + ResourceGroupListStep, + SubscriptionTreeItemBase, + VerifyProvidersStep, +} from "@microsoft/vscode-azext-azureutils"; +import { + AzExtFsExtra, + AzureWizard, + nonNullProp, + type AzureWizardExecuteStep, + type AzureWizardPromptStep, + type ExecuteActivityContext, + type IActionContext, + type ICreateChildImplContext, +} from "@microsoft/vscode-azext-utils"; +import type { AppResource } from "@microsoft/vscode-azext-utils/hostapi"; +import type { Octokit } from "@octokit/rest"; +import { homedir } from "os"; +import { join } from "path"; +import { + ProgressLocation, + Uri, + window, + workspace, + type ProgressOptions, + type WorkspaceFolder, +} from "vscode"; +import { Utils } from "vscode-uri"; +import { StaticWebAppResolver } from "../../StaticWebAppResolver"; +import { + NodeDetector, + type DetectorResults, +} from "../../detectors/node/NodeDetector"; +import { NodeConstants } from "../../detectors/node/nodeConstants"; +import { VerifyingWorkspaceError } from "../../errors"; +import { ext } from "../../extensionVariables"; +import { createActivityContext } from "../../utils/activityUtils"; +import { createWebSiteClient } from "../../utils/azureClients"; +import { cpUtils } from "../../utils/cpUtils"; +import { getGitHubAccessToken } from "../../utils/gitHubUtils"; +import { gitPull } from "../../utils/gitUtils"; +import { localize } from "../../utils/localize"; +import { telemetryUtils } from "../../utils/telemetryUtils"; +import { + getSingleRootFsPath, + getSubFolders, + showNoWorkspacePrompt, + tryGetWorkspaceFolder, +} from "../../utils/workspaceUtils"; +import { RemoteShortnameStep } from "../createRepo/RemoteShortnameStep"; +import { RepoCreateStep } from "../createRepo/RepoCreateStep"; +import { RepoNameStep } from "../createRepo/RepoNameStep"; +import { RepoPrivacyStep } from "../createRepo/RepoPrivacyStep"; +import { createOctokitClient } from "../github/createOctokitClient"; +import { showSwaCreated } from "../showSwaCreated"; +import { ApiLocationStep } from "./ApiLocationStep"; +import { AppLocationStep } from "./AppLocationStep"; +import { BuildPresetListStep } from "./BuildPresetListStep"; +import { GitHubOrgListStep } from "./GitHubOrgListStep"; +import type { IStaticWebAppWizardContext } from "./IStaticWebAppWizardContext"; +import { OutputLocationStep } from "./OutputLocationStep"; +import { SkuListStep } from "./SkuListStep"; +import { StaticWebAppCreateStep } from "./StaticWebAppCreateStep"; +import { StaticWebAppNameStep } from "./StaticWebAppNameStep"; +import { setGitWorkspaceContexts } from "./setWorkspaceContexts"; +import { tryGetApiLocations } from "./tryGetApiLocations"; + +function isSubscription( + item?: SubscriptionTreeItemBase +): item is SubscriptionTreeItemBase { + try { + // Accessing item.subscription throws an error for some workspace items + // see https://github.com/microsoft/vscode-azurefunctions/issues/3731 + return !!item && !!item.subscription; + } catch { + return false; + } } -let isVerifyingWorkspace: boolean = false; -export async function createStaticWebApp(context: IActionContext & Partial & Partial, node?: SubscriptionTreeItemBase): Promise { - if (isVerifyingWorkspace) { - throw new VerifyingWorkspaceError(context); +let isVerifyingWorkspace = false; +export async function createStaticWebApp( + context: IActionContext & + Partial & + Partial, + node?: SubscriptionTreeItemBase, + _nodes?: SubscriptionTreeItemBase[], + ...args: unknown[] +): Promise { + const isLogicAppParameterPassed = args.length > 0; + if (isLogicAppParameterPassed) { + type Resource = { backendResourceId: string; region: string; name: string }; + const logicApp = args[0] as Resource; + context.shouldInitLogicApp = logicApp; + return await createStaticWebAppWithLogicApp(context); + } + + if (isVerifyingWorkspace) { + throw new VerifyingWorkspaceError(context); + } + const progressOptions: ProgressOptions = { + location: ProgressLocation.Window, + title: localize("verifyingWorkspace", "Verifying workspace..."), + }; + isVerifyingWorkspace = true; + try { + if (!isSubscription(node)) { + node = + await ext.rgApi.appResourceTree.showTreeItemPicker( + SubscriptionTreeItemBase.contextValue, + context + ); } + await window.withProgress(progressOptions, async () => { + const folder = await tryGetWorkspaceFolder(context); + if (folder) { + await telemetryUtils.runWithDurationTelemetry( + context, + "tryGetFrameworks", + async () => { + const detector = new NodeDetector(); - const progressOptions: ProgressOptions = { - location: ProgressLocation.Window, - title: localize('verifyingWorkspace', 'Verifying workspace...') - }; - - isVerifyingWorkspace = true; - try { - if (!isSubscription(node)) { - node = await ext.rgApi.appResourceTree.showTreeItemPicker(SubscriptionTreeItemBase.contextValue, context); - } - - await window.withProgress(progressOptions, async () => { - const folder = await tryGetWorkspaceFolder(context); - if (folder) { - await telemetryUtils.runWithDurationTelemetry(context, 'tryGetFrameworks', async () => { - const detector = new NodeDetector(); - - const detectorResult = await detector.detect(folder.uri); - // comma separated list of all frameworks detected in this project - context.telemetry.properties.detectedFrameworks = `(${detectorResult?.frameworks.map(fi => fi.framework).join('), (')})` ?? 'N/A'; - context.telemetry.properties.rootHasSrcFolder = (await AzExtFsExtra.pathExists(Uri.joinPath(folder.uri, NodeConstants.srcFolderName))).toString(); - - const subfolderDetectorResults: DetectorResults[] = []; - const subWithSrcFolder: string[] = [] - const subfolders = await getSubFolders(context, folder.uri); - for (const subfolder of subfolders) { - const subResult = await detector.detect(subfolder); - if (subResult) { - subfolderDetectorResults.push(subResult); - if (await AzExtFsExtra.pathExists(Uri.joinPath(subfolder, NodeConstants.srcFolderName))) { - subWithSrcFolder.push(Utils.basename(subfolder)); - } - } - } - - if (subfolderDetectorResults.length > 0) { - // example print: "(Angular,Typescript), (Next.js,React), (Nuxt.js), (React), (Svelte), (Vue.js,Vue.js)" - context.telemetry.properties.detectedFrameworksSub = `(${subfolderDetectorResults.map(dr => dr.frameworks).map(fis => fis.map(fi => fi.framework)).join('), (')})`; - context.telemetry.properties.subFoldersWithSrc = subWithSrcFolder.join(', '); - } - }); - - await setGitWorkspaceContexts(context, folder); - context.detectedApiLocations = await tryGetApiLocations(context, folder); - } else { - await showNoWorkspacePrompt(context); + const detectorResult = await detector.detect(folder.uri); + // comma separated list of all frameworks detected in this project + context.telemetry.properties.detectedFrameworks = + `(${detectorResult?.frameworks + .map((fi) => fi.framework) + .join("), (")})` ?? "N/A"; + context.telemetry.properties.rootHasSrcFolder = ( + await AzExtFsExtra.pathExists( + Uri.joinPath(folder.uri, NodeConstants.srcFolderName) + ) + ).toString(); + const subfolderDetectorResults: DetectorResults[] = []; + const subWithSrcFolder: string[] = []; + const subfolders = await getSubFolders(context, folder.uri); + for (const subfolder of subfolders) { + const subResult = await detector.detect(subfolder); + if (subResult) { + subfolderDetectorResults.push(subResult); + if ( + await AzExtFsExtra.pathExists( + Uri.joinPath(subfolder, NodeConstants.srcFolderName) + ) + ) { + subWithSrcFolder.push(Utils.basename(subfolder)); + } + } + } + if (subfolderDetectorResults.length > 0) { + // example print: "(Angular,Typescript), (Next.js,React), (Nuxt.js), (React), (Svelte), (Vue.js,Vue.js)" + context.telemetry.properties.detectedFrameworksSub = `(${subfolderDetectorResults + .map((dr) => dr.frameworks) + .map((fis) => fis.map((fi) => fi.framework)) + .join("), (")})`; + context.telemetry.properties.subFoldersWithSrc = + subWithSrcFolder.join(", "); } - }); - } finally { - isVerifyingWorkspace = false; + } + ); + await setGitWorkspaceContexts(context, folder); + context.detectedApiLocations = await tryGetApiLocations( + context, + folder + ); + } else { + await showNoWorkspacePrompt(context); + } + }); + } finally { + isVerifyingWorkspace = false; + } + const client: WebSiteManagementClient = await createWebSiteClient([ + context, + node.subscription, + ]); + const wizardContext: IStaticWebAppWizardContext = { + accessToken: await getGitHubAccessToken(), + client, + ...context, + ...node.subscription, + ...(await createActivityContext()), + }; + const title: string = localize("createStaticApp", "Create Static Web App"); + const promptSteps: AzureWizardPromptStep< + IStaticWebAppWizardContext & ExecuteActivityContext + >[] = []; + const executeSteps: AzureWizardExecuteStep[] = []; + if (!context.advancedCreation) { + wizardContext.sku = SkuListStep.getSkus()[0]; + executeSteps.push(new ResourceGroupCreateStep()); + } else { + promptSteps.push(new ResourceGroupListStep()); + } + promptSteps.push(new StaticWebAppNameStep(), new SkuListStep()); + const hasRemote: boolean = !!wizardContext.repoHtmlUrl; + // if the local project doesn't have a GitHub remote, we will create it for them + if (!hasRemote) { + promptSteps.push( + new GitHubOrgListStep(), + new RepoNameStep(), + new RepoPrivacyStep(), + new RemoteShortnameStep() + ); + executeSteps.push(new RepoCreateStep()); + } + // hard-coding locations available during preview + // https://github.com/microsoft/vscode-azurestaticwebapps/issues/18 + const locations = [ + "Central US", + "East US 2", + "East Asia", + "West Europe", + "West US 2", + ]; + const webProvider: string = "Microsoft.Web"; + LocationListStep.setLocationSubset( + wizardContext, + Promise.resolve(locations), + webProvider + ); + LocationListStep.addStep(wizardContext, promptSteps, { + placeHolder: localize( + "selectLocation", + "Select a region for Azure Functions API and staging environments" + ), + noPicksMessage: localize("noRegions", "No available regions."), + }); + promptSteps.push( + new BuildPresetListStep(), + new AppLocationStep(), + new ApiLocationStep(), + new OutputLocationStep() + ); + executeSteps.push(new VerifyProvidersStep([webProvider])); + executeSteps.push(new StaticWebAppCreateStep()); + const wizard: AzureWizard = new AzureWizard( + wizardContext, + { + title, + promptSteps, + executeSteps, + showLoadingPrompt: true, } - const client: WebSiteManagementClient = await createWebSiteClient([context, node.subscription]); - const wizardContext: IStaticWebAppWizardContext = { - accessToken: await getGitHubAccessToken(), - client, - ...context, - ...node.subscription, - ...(await createActivityContext()) - }; - - const title: string = localize('createStaticApp', 'Create Static Web App'); - const promptSteps: AzureWizardPromptStep[] = []; - const executeSteps: AzureWizardExecuteStep[] = []; - - if (!context.advancedCreation) { - wizardContext.sku = SkuListStep.getSkus()[0]; - executeSteps.push(new ResourceGroupCreateStep()); - } else { - promptSteps.push(new ResourceGroupListStep()); + ); + wizardContext.telemetry.properties.gotRemote = String(hasRemote); + wizardContext.uri = wizardContext.uri || getSingleRootFsPath(); + wizardContext.telemetry.properties.numberOfWorkspaces = + !workspace.workspaceFolders + ? String(0) + : String(workspace.workspaceFolders.length); + await wizard.prompt(); + wizardContext.activityTitle = localize( + "createStaticApp", + 'Create Static Web App "{0}"', + nonNullProp(wizardContext, "newStaticWebAppName") + ); + if (!context.advancedCreation) { + wizardContext.newResourceGroupName = await wizardContext.relatedNameTask; + } + await wizard.execute(); + await ext.rgApi.appResourceTree.refresh(context); + const swa: StaticSiteARMResource = nonNullProp(wizardContext, "staticWebApp"); + await gitPull(nonNullProp(wizardContext, "repo")); + const appResource: AppResource = { + id: nonNullProp(swa, "id"), + name: nonNullProp(swa, "name"), + type: nonNullProp(swa, "type"), + ...swa, + }; + const resolver = new StaticWebAppResolver(); + const resolvedSwa = await resolver.resolveResource( + node.subscription, + appResource + ); + if (resolvedSwa) { + await showSwaCreated(resolvedSwa); + } + return appResource; +} + +export async function createStaticWebAppWithLogicApp( + context: IActionContext & + Partial & + Partial, + node?: SubscriptionTreeItemBase +): Promise { + if (isVerifyingWorkspace) { + throw new VerifyingWorkspaceError(context); + } + const progressOptions: ProgressOptions = { + location: ProgressLocation.Window, + title: localize("verifyingWorkspace", "Verifying workspace..."), + }; + + isVerifyingWorkspace = true; + if (!isSubscription(node)) { + node = + await ext.rgApi.appResourceTree.showTreeItemPicker( + SubscriptionTreeItemBase.contextValue, + context + ); + } + const client: WebSiteManagementClient = await createWebSiteClient([ + context, + node.subscription, + ]); + const wizardContext: IStaticWebAppWizardContext = { + accessToken: await getGitHubAccessToken(), + client, + ...context, + ...node.subscription, + ...(await createActivityContext()), + }; + const title: string = localize("createStaticApp", "Create Static Web App"); + const promptSteps: AzureWizardPromptStep< + IStaticWebAppWizardContext & ExecuteActivityContext + >[] = []; + const executeSteps: AzureWizardExecuteStep[] = []; + if (!context.advancedCreation) { + //[1] gets standard and not free + wizardContext.sku = SkuListStep.getSkus()[1]; + executeSteps.push(new ResourceGroupCreateStep()); + } else { + promptSteps.push(new ResourceGroupListStep()); + } + + promptSteps.push(new StaticWebAppNameStep(), new SkuListStep()); + const wizard: AzureWizard = new AzureWizard( + wizardContext, + { + title, + promptSteps, + executeSteps, + showLoadingPrompt: true, } + ); - promptSteps.push(new StaticWebAppNameStep(), new SkuListStep()); - const hasRemote: boolean = !!wizardContext.repoHtmlUrl; + wizardContext.uri = wizardContext.uri || getSingleRootFsPath(); + await wizard.prompt(); - // if the local project doesn't have a GitHub remote, we will create it for them - if (!hasRemote) { - promptSteps.push(new GitHubOrgListStep(), new RepoNameStep(), new RepoPrivacyStep(), new RemoteShortnameStep()); - executeSteps.push(new RepoCreateStep()); + //create github template (TODO 7: Make this a function) + const folderName: string = getFolderName(wizardContext); + const homeDir = homedir(); + const clonePath = getClonePath(homeDir, folderName); + const clonePathUri: Uri = Uri.file(clonePath); + const octokitClient: Octokit = await createOctokitClient(context); + const { data: response } = await octokitClient.rest.repos.createUsingTemplate( + { + private: true, + template_owner: "alain-zhiyanov", + template_repo: "template-swa-la", + name: folderName, } + ); + await sleep(1000); - // hard-coding locations available during preview - // https://github.com/microsoft/vscode-azurestaticwebapps/issues/18 - const locations = [ - 'Central US', - 'East US 2', - 'East Asia', - 'West Europe', - 'West US 2' - ]; - - const webProvider: string = 'Microsoft.Web'; - - LocationListStep.setLocationSubset(wizardContext, Promise.resolve(locations), webProvider); - LocationListStep.addStep(wizardContext, promptSteps, { - placeHolder: localize('selectLocation', 'Select a region for Azure Functions API and staging environments'), - noPicksMessage: localize('noRegions', 'No available regions.') - }); + //clone github template + const repoUrl = response.html_url; + const command = `git clone ${repoUrl} ${clonePath}`; + await fs.mkdir(clonePath, { recursive: true }); + await cpUtils.executeCommand(undefined, clonePath, command); - promptSteps.push(new BuildPresetListStep(), new AppLocationStep(), new ApiLocationStep(), new OutputLocationStep()); + await tryGetWorkspaceFolder(context); + try { + await window.withProgress(progressOptions, async () => { + const folder: WorkspaceFolder = { + uri: clonePathUri, + name: "myUri", + index: 0, + }; + if (folder) { + await telemetryUtils.runWithDurationTelemetry( + context, + "tryGetFrameworks", + async () => { + const detector = new NodeDetector(); + const detectorResult = await detector.detect(folder.uri); + // comma separated list of all frameworks detected in this project + context.telemetry.properties.detectedFrameworks = + `(${detectorResult?.frameworks + .map((fi) => fi.framework) + .join("), (")})` ?? "N/A"; + context.telemetry.properties.rootHasSrcFolder = ( + await AzExtFsExtra.pathExists( + Uri.joinPath(folder.uri, NodeConstants.srcFolderName) + ) + ).toString(); - executeSteps.push(new VerifyProvidersStep([webProvider])); - executeSteps.push(new StaticWebAppCreateStep()); + const subfolderDetectorResults: DetectorResults[] = []; + const subWithSrcFolder: string[] = []; + const subfolders = await getSubFolders(context, folder.uri); + for (const subfolder of subfolders) { + const subResult = await detector.detect(subfolder); + if (subResult) { + subfolderDetectorResults.push(subResult); + if ( + await AzExtFsExtra.pathExists( + Uri.joinPath(subfolder, NodeConstants.srcFolderName) + ) + ) { + subWithSrcFolder.push(Utils.basename(subfolder)); + } + } + } - const wizard: AzureWizard = new AzureWizard(wizardContext, { - title, - promptSteps, - executeSteps, - showLoadingPrompt: true + if (subfolderDetectorResults.length > 0) { + // example print: "(Angular,Typescript), (Next.js,React), (Nuxt.js), (React), (Svelte), (Vue.js,Vue.js)" + context.telemetry.properties.detectedFrameworksSub = `(${subfolderDetectorResults + .map((dr) => dr.frameworks) + .map((fis) => fis.map((fi) => fi.framework)) + .join("), (")})`; + context.telemetry.properties.subFoldersWithSrc = + subWithSrcFolder.join(", "); + } + } + ); + + await setGitWorkspaceContexts(context, folder); + context.detectedApiLocations = await tryGetApiLocations( + context, + folder + ); + } else { + await showNoWorkspacePrompt(context); + } }); + } finally { + isVerifyingWorkspace = false; + } + let hasRemote = false; + if (wizardContext.repoHtmlUrl !== null) { + hasRemote = true; + } + wizardContext.telemetry.properties.gotRemote = String(hasRemote); + // if the local project doesn't have a GitHub remote, we will create it for them + // this used to be right below website management client, maybe doesn't even need to be ran? + if (!hasRemote) { + promptSteps.push( + new GitHubOrgListStep(), + new RepoNameStep(), + new RepoPrivacyStep(), + new RemoteShortnameStep() + ); - wizardContext.telemetry.properties.gotRemote = String(hasRemote); - wizardContext.uri = wizardContext.uri || getSingleRootFsPath(); - wizardContext.telemetry.properties.numberOfWorkspaces = !workspace.workspaceFolders ? String(0) : String(workspace.workspaceFolders.length); + executeSteps.push(new RepoCreateStep()); + } - await wizard.prompt(); + // hard-coding locations available during preview + // https://github.com/microsoft/vscode-azurestaticwebapps/issues/18 + const locations = [ + "Central US", + "East US 2", + "East Asia", + "West Europe", + "West US 2", + ]; - wizardContext.activityTitle = localize('createStaticApp', 'Create Static Web App "{0}"', nonNullProp(wizardContext, 'newStaticWebAppName')); + const webProvider: string = "Microsoft.Web"; - if (!context.advancedCreation) { - wizardContext.newResourceGroupName = await wizardContext.relatedNameTask; - } + LocationListStep.setLocationSubset( + wizardContext, + Promise.resolve(locations), + webProvider + ); + LocationListStep.addStep(wizardContext, promptSteps, { + placeHolder: localize( + "selectLocation", + "Select a region for Azure Functions API and staging environments" + ), + noPicksMessage: localize("noRegions", "No available regions."), + }); - await wizard.execute(); + promptSteps.push( + new BuildPresetListStep(), + new AppLocationStep(), + new ApiLocationStep(), + new OutputLocationStep() + ); - await ext.rgApi.appResourceTree.refresh(context); - const swa: StaticSiteARMResource = nonNullProp(wizardContext, 'staticWebApp'); - await gitPull(nonNullProp(wizardContext, 'repo')); + executeSteps.push(new VerifyProvidersStep([webProvider])); + executeSteps.push(new StaticWebAppCreateStep()); - const appResource: AppResource = { - id: nonNullProp(swa, 'id'), - name: nonNullProp(swa, 'name'), - type: nonNullProp(swa, 'type'), - ...swa - }; + wizardContext.telemetry.properties.numberOfWorkspaces = + !workspace.workspaceFolders + ? String(0) + : String(workspace.workspaceFolders.length); - const resolver = new StaticWebAppResolver(); - const resolvedSwa = await resolver.resolveResource(node.subscription, appResource); - if (resolvedSwa) { - await showSwaCreated(resolvedSwa); - } + await wizard.prompt(); + + wizardContext.activityTitle = localize( + "createStaticApp", + 'Create Static Web App "{0}"', + nonNullProp(wizardContext, "newStaticWebAppName") + ); + + if (!context.advancedCreation) { + wizardContext.newResourceGroupName = await wizardContext.relatedNameTask; + } + + await wizard.execute(); + + await ext.rgApi.appResourceTree.refresh(context); + const swa: StaticSiteARMResource = nonNullProp(wizardContext, "staticWebApp"); + await gitPull(nonNullProp(context, "repo")); + + const appResource: AppResource = { + id: nonNullProp(swa, "id"), + name: nonNullProp(swa, "name"), + type: nonNullProp(swa, "type"), + ...swa, + }; + + const resolver = new StaticWebAppResolver(); + const resolvedSwa = await resolver.resolveResource( + node.subscription, + appResource + ); + if (resolvedSwa) { + await showSwaCreated(resolvedSwa); + } + + return appResource; +} + +function getClonePath(homeDir: string, folderName: string) { + const baseClonePath = join(homeDir, folderName); + const clonePath = join(baseClonePath, "static-web-app"); + return clonePath; +} + +function getFolderName(wizardContext: IStaticWebAppWizardContext): string { + return wizardContext.newStaticWebAppName || "default_folder_name"; +} - return appResource; +export async function createStaticWebAppAdvanced( + context: IActionContext, + node?: SubscriptionTreeItemBase +): Promise { + return await createStaticWebApp({ ...context, advancedCreation: true }, node); } -export async function createStaticWebAppAdvanced(context: IActionContext, node?: SubscriptionTreeItemBase): Promise { - return await createStaticWebApp({ ...context, advancedCreation: true }, node); +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); } diff --git a/src/commands/registerCommands.ts b/src/commands/registerCommands.ts index 310b49a1e..5e5a14d37 100644 --- a/src/commands/registerCommands.ts +++ b/src/commands/registerCommands.ts @@ -25,7 +25,7 @@ import { openGitHubLog } from './github/jobLogs/openGitHubLog'; import { openGitHubRepo } from './github/openGitHubRepo'; import { showActions } from './github/showActions'; import { openInPortal } from './openInPortal'; -import { openYAMLConfigFile } from './openYAMLConfigFile'; +import { openYAMLConfigFile } from "./openYAMLConfigFile"; import { viewProperties } from './viewProperties'; export function registerCommands(): void {